SGU 521 North-East ( 二维LIS 线段树优化 )
521. "North-East"
Memory limit: 262144 kilobytes
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.
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 integersxi, yi (-106 ≤ xi, yi ≤ 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.
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.
sample input |
sample output |
5 |
5 1 2 3 4 5 |
sample input |
sample output |
5 |
4 1 2 3 5 |
题意是可以从某个点出发,走向 x , y 都严格增大的点走 , 问那些点可能在最长路径上 ,那些点必定会经过
用 dp[0][i] 表示点i 作为右端点的最长路 , dp[1][i] 表示点i 作为左端点的最长路 。
再判一下 dp[0][i] + dp[1][i] 是否跟最大值相等 , 就可知道它是否第一类点。
而第二类点直接用一个cnt数组记录一下数字的出现次数是否唯一即可判断 ~
#include <bits/stdc++.h>
using namespace std ;
const int N = ; 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<<] ; void Up( int rt ) {
mx[rt] = max( mx[lr] , mx[rr] ) ;
} void Build( int l , int r , int rt ) {
mx[rt] = ;
if( l == r ) return ;
int mid = ( l+r ) >> ;
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)>>;
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) >> ;
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 + , 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<int,int>idx;
vector<int>a;
int S[N] , top ; vector<int> ans1 , ans2 ;
int cnt[N] , dp[][N] ; void Doit( int k , int p ) {
for( int i = top - ; i >= ; --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 , , sizeof dp ) ;
memset( cnt , , sizeof cnt ) ; sort( e + , e + n + , cmp1 ) ;
T.Build( root ) ; top = ;
for( int i = ; i <= n ; ++i ) {
int id = idx[ e[i].y ] ;
if( i == n || e[i].x != e[i+].x ) {
S[top++] = T.Query( root , , id - ) + ;
Doit( , i );
top = ;
} else {
S[top++] = T.Query( root , , id - ) + ;
}
}
sort( e + , e + n + , cmp2 ) ;
T.Build( root ) ; top = ;
for( int i = ; i <= n ; ++i ) {
int id = idx[ e[i].y ] ;
if( i == n || e[i].x != e[i+].x ) {
S[top++] = T.Query( root , id + , n + ) + ;
Doit( , i );
top = ;
} else {
S[top++] = T.Query( root , id + , n + ) + ;
}
} // 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 = ;
for( int i = ; i <= n ; ++i ) len = max( len , dp[][i] + dp[][i] ) ;
for( int i = ; i <= n ; ++i ) if( dp[][ e[i].id ] + dp[][ e[i].id ] == len ) ans1.push_back( e[i].id ) , cnt[ dp[][ e[i].id ] ]++ ;
for( int i = ; i <= n ; ++i ) if( dp[][ e[i].id ] + dp[][ e[i].id ] == len && cnt[ dp[][e[i].id] ] == ) 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 = ; i < ans1.size() ; ++i ) printf(" %d",ans1[i]);puts("");
printf("%d",ans2.size()); for( int i = ; i < ans2.size() ; ++i ) printf(" %d",ans2[i]);puts("");
} int main() {
while( ~scanf("%d",&n) ) {
idx.clear(); a.clear();
for( int i = ; 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 = ;
for( int i = ; i < a.size() ; ++i ) {
if( idx.find( a[i] ) == idx.end() ) {
idx[ a[i] ] = tot++ ;
}
}
Gao(); Output();
}
return ;
}
SGU 521 North-East ( 二维LIS 线段树优化 )的更多相关文章
- 二维$MLE$线段树
关于二维线段树,ta死了 先来看看两种二维线段树的打法 1.四叉树 然而ta死了,ta是$\Theta (n)$的,加上线段树的常数,$T$飞稳 2.线段树套线段树 我尽量画出来... 图中每个方块是 ...
- D. Babaei and Birthday Cake---cf629D(LIS线段树优化)
题目链接:http://codeforces.com/problemset/problem/629/D 题意就是现有n个蛋糕,蛋糕的形状是圆柱体,每个蛋糕的体积就是圆柱体的体积,每个蛋糕的编号是1-- ...
- 二维LIS(CDQ分治)
题目描述 给定一个长度为N的序列S,S的每个元素pi是一个二元组(xi,yi),定义pi<pj当且仅当xi<xj并且yi<yj,求S的最长上升子序列长度 输入格式 第一行一个N,表示 ...
- HDU 1160 FatMouse's Speed(要记录路径的二维LIS)
FatMouse's Speed Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- BZOJ2244: [SDOI2011]拦截导弹(CDQ分治,二维LIS,计数)
Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高 ...
- (转载)Android项目实战(二十八):Zxing二维码实现及优化
Android项目实战(二十八):Zxing二维码实现及优化 前言: 多年之前接触过zxing实现二维码,没想到今日项目中再此使用竟然使用的还是zxing,百度之,竟是如此牛的玩意. 当然,项目中 ...
- 【bzoj3939】[Usaco2015 Feb]Cow Hopscotch 动态开点线段树优化dp
题目描述 Just like humans enjoy playing the game of Hopscotch, Farmer John's cows have invented a varian ...
- hdu 3698 UVA1490 Let the light guide us 线段树优化DP
题目链接 and 题目大意 hdu3698 但是 hdu的数据比较弱,所以在这luogu提交吧UVA1490 Let the light guide us 有一个\(n*m\)的平原,要求每行选一个点 ...
- UVA-1322 Minimizing Maximizer (DP+线段树优化)
题目大意:给一个长度为n的区间,m条线段序列,找出这个序列的一个最短子序列,使得区间完全被覆盖. 题目分析:这道题不难想,定义状态dp(i)表示用前 i 条线段覆盖区间1~第 i 线段的右端点需要的最 ...
随机推荐
- 开发一个chrome插件:将百度搜索热点屏蔽掉!
每次百度搜索,搜索结果的右边总是出现些乱七八糟的搜索热点(推的都是些什么玩意,高校替课和我有毛关系,几个悲伤的热点我用星号顶掉了). 强迫症想把它隐藏掉,我用的是chrome浏览器,受adblock( ...
- #418 Div2 Problem B An express train to reveries (构造 || 全排列序列特性)
题目链接:http://codeforces.com/contest/814/problem/B 题意 : 有一个给出两个含有 n 个数的序列 a 和 b, 这两个序列和(1~n)的其中一个全排列序列 ...
- 文件操作:rewind()
函数名: rewind() 功 能: 将文件内部的位置指针重新指向一个流(数据流/文件)的开头 注意:不是文件指针而是文件内部的位置指针,随着对文件的读写文件的位置指针(指向当前读写字节)向后移动 ...
- Linux系统安装时分区的介绍
一般来说,在linux系统中都有最少两个挂载点,分别是/ (根目录)及 swap(交换分区),其中,/ 是必须的: 建议挂载的几大目录: /-------根目录,唯一必须挂载的目录.不要有任何的犹豫, ...
- es之批量提交操作
1:批量查询操作 1):插入测试数据 PUT /costumer/doc/1{ "name": "zhangsan", "age": 20} ...
- [BZOJ2729]:[HNOI2012]排队(组合数学)
题目传送门 题目描述 某中学有n名男同学,m名女同学和两名老师要排队参加体检.他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不同的) ...
- taihong
揭秘!除了台风 我们还能在卫星云图上看到什么? 2019-08-08 09:20:53 来源: 中国天气网 中国天气网讯 说到卫星云图,可能大多数人首先能想到的就是台风.其实,拥有太空视角的卫星能 ...
- webpack插件之webpack-dev-server
webpack插件之webpack-dev-server webpack插件 自动化 webpack-dev-server 现在只需要使用 npm run build指令就可以自动打包,并自动处理好 ...
- eclipse link方式安装插件安装不上
只能要features和plugins两个文件夹,其他文件需要删除
- Python Module_openpyxl_处理Excel表格
目录 目录 前言 软件系统 Install openpyxl module Sample code load_workbook加载Excel文件 wbObjectget_sheet_names 获取E ...