博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SGU 521 North-East ( 二维LIS 线段树优化 )
阅读量:6980 次
发布时间:2019-06-27

本文共 6083 字,大约阅读时间需要 20 分钟。

521. "North-East"

Time limit per test: 0.5 second(s)
Memory limit: 262144 kilobytes
input: standard
output: standard

The popular music band of international fame "North-East" is coming to Berland! This news has spread all over the country, so numerous fans are now ready to rush and buy all the tickets!
At present the fans still don't know in which cities the band plans to give concerts. The only thing is known at the moment is that the band will visit several cities, and as their name says, they will strictly move north and east when going to the next city. In other words when the band moves from city i to city j, city j is always located northward and eastward of the city i.
It's also known that the tour is planned in such a way that the maximum possible number of cities will be visited. The musicians refuse to reveal other details. As you know, fans always get ready for the arrival of their idols, so they would appreciate any single detail about possible movements of their favorite musicians.
Your task is to help the fans and find two lists of cities — A and B. The first list A should contain the cities, which the band might visit during the tour. The second list B should contain the cities, which the band will have to visit for sure during the tour.

Input

The first line of input contains a single integer n (1 ≤ n ≤ 105) — amount of cities in the country. The following n lines contain coordinates of the cities. Each line contains a pair of integersxiyi (-106 ≤ xiyi ≤ 106) — the coordinates of the i-th city. Ox axis is directed west-to-east, and Oy axis — south-to-north. No two given cities will be located at the same point.

Output

Print the required list A to the first line of output and B to the second line. Each list should start with the amount of cities in it, followed by the indices of cities in increasing order. Cities are numbered from 1 to n.

Example(s)
sample input
sample output
53 21 15 52 34 4
5 1 2 3 4 53 2 3 5

 

sample input
sample output
51 110 105 610 16 5
4 1 2 3 52 1 2

 

 

题意是可以从某个点出发,走向 x , y 都严格增大的点走 , 问那些点可能在最长路径上 ,那些点必定会经过

 

用 dp[0][i] 表示点i 作为右端点的最长路 , dp[1][i] 表示点i 作为左端点的最长路 。

再判一下 dp[0][i] + dp[1][i]  是否跟最大值相等 , 就可知道它是否第一类点。

而第二类点直接用一个cnt数组记录一下数字的出现次数是否唯一即可判断 ~

#include 
using namespace std ;const int N = 200020 ;int n ;struct SegTree { #define root 1,n+10,1 #define lr rt<<1 #define rr rt<<1|1 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 int mx[N<<2] ; void Up( int rt ) { mx[rt] = max( mx[lr] , mx[rr] ) ; } void Build( int l , int r , int rt ) { mx[rt] = 0 ; if( l == r ) return ; int mid = ( l+r ) >> 1 ; Build(lson),Build(rson) ; } void Update( int l , int r , int rt , int x , int v ) { if( l == r ) { mx[rt] = v ; return ; } int mid = (l+r)>>1; if( x <= mid ) Update( lson , x , v ); else Update( rson , x , v); Up(rt); } int Query( int l , int r , int rt , int L , int R ) { if( l == L && r == R ) return mx[rt] ; int mid = (l+r) >> 1 ; if( R <= mid ) return Query( lson , L , R ) ; else if( L > mid ) return Query( rson , L , R ) ; else return max( Query( lson , L , mid ) , Query( rson , mid + 1 , R ) ) ; }} T;struct node { int x , y , id ; } e[N] ;inline bool cmp1( const node &a , const node &b ) { if( a.x != b.x ) return a.x < b.x ; else return a.y < b.y ;}inline bool cmp2( const node &a , const node &b ) { if( a.x != b.x ) return a.x > b.x ; else return a.y > b.y ;}map
idx;vector
a;int S[N] , top ;vector
ans1 , ans2 ;int cnt[N] , dp[2][N] ;void Doit( int k , int p ) { for( int i = top - 1 ; i >= 0 ; --i ) { int id = idx[ e[p].y ] ; dp[k][ e[p].id ] = S[i] ; T.Update( root , id , S[i] ); p-- ; }}void Gao() { memset( dp , 0 , sizeof dp ) ; memset( cnt , 0 , sizeof cnt ) ; sort( e + 1 , e + n + 1 , cmp1 ) ; T.Build( root ) ; top = 0 ; for( int i = 1 ; i <= n ; ++i ) { int id = idx[ e[i].y ] ; if( i == n || e[i].x != e[i+1].x ) { S[top++] = T.Query( root , 1 , id - 1 ) + 1 ; Doit( 0 , i ); top = 0 ; } else { S[top++] = T.Query( root , 1 , id - 1 ) + 1 ; } } sort( e + 1 , e + n + 1 , cmp2 ) ; T.Build( root ) ; top = 0 ; for( int i = 1 ; i <= n ; ++i ) { int id = idx[ e[i].y ] ; if( i == n || e[i].x != e[i+1].x ) { S[top++] = T.Query( root , id + 1 , n + 10 ) + 1 ; Doit( 1 , i ); top = 0 ; } else { S[top++] = T.Query( root , id + 1 , n + 10 ) + 1 ; } }// for( int i = 1 ; i <= n ; ++i ) cout << e[i].id << ' ' << dp[0][ e[i].id ] << ' ' << dp[1][ e[i].id ] << endl ; ans1.clear() , ans2.clear() ; int len = 0 ; for( int i = 1 ; i <= n ; ++i ) len = max( len , dp[0][i] + dp[1][i] ) ; for( int i = 1 ; i <= n ; ++i ) if( dp[0][ e[i].id ] + dp[1][ e[i].id ] == len ) ans1.push_back( e[i].id ) , cnt[ dp[0][ e[i].id ] ]++ ; for( int i = 1 ; i <= n ; ++i ) if( dp[0][ e[i].id ] + dp[1][ e[i].id ] == len && cnt[ dp[0][e[i].id] ] == 1 ) ans2.push_back( e[i].id ) ;}void Output() { sort( ans1.begin() , ans1.end() ) , sort( ans2.begin() , ans2.end() ) ; printf("%d",ans1.size()); for( int i = 0 ; i < ans1.size() ; ++i ) printf(" %d",ans1[i]);puts(""); printf("%d",ans2.size()); for( int i = 0 ; i < ans2.size() ; ++i ) printf(" %d",ans2[i]);puts("");}int main() { while( ~scanf("%d",&n) ) { idx.clear(); a.clear(); for( int i = 1 ; i <= n ; ++i ) { scanf("%d%d",&e[i].x,&e[i].y); e[i].id = i ; a.push_back( e[i].y ); } sort( a.begin() , a.end() ) ; int tot = 2 ; for( int i = 0 ; i < a.size() ; ++i ) { if( idx.find( a[i] ) == idx.end() ) { idx[ a[i] ] = tot++ ; } } Gao(); Output(); } return 0 ; }
View Code

 

转载于:https://www.cnblogs.com/hlmark/p/4521496.html

你可能感兴趣的文章
前端的一些小的效果
查看>>
angular指令ng-class巧用
查看>>
解密FFmpeg播放track mode控制
查看>>
前端基础之JavaScript
查看>>
暂时喘口气,
查看>>
xp命令大全
查看>>
python装饰器+迭代器+生成器
查看>>
Sencha-概念-Layouts(布局)(官网文档翻译8)
查看>>
swift的特点
查看>>
去除ios input部分默认样式
查看>>
【HDOJ】3275 Light
查看>>
Spring中使用Schedule调度
查看>>
老毛桃PE
查看>>
Hadoop生态圈-Flume的组件之自定义拦截器(interceptor)
查看>>
WaveSwipeRefreshLayout
查看>>
C#编程(十二)----------函数
查看>>
【教程】【FLEX】#004 反射机制
查看>>
K:java中的序列化与反序列化
查看>>
23.week4
查看>>
互联网+和创业潮,互联网+前提条件是什么?互联网+做什么?
查看>>