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
5
3 2
1 1
5 5
2 3
4 4
5 1 2 3 4 5
3 2 3 5
sample input
sample output
5
1 1
10 10
5 6
10 1
6 5
4 1 2 3 5
2 1 2

题意是可以从某个点出发,走向 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 线段树优化 )的更多相关文章

  1. 二维$MLE$线段树

    关于二维线段树,ta死了 先来看看两种二维线段树的打法 1.四叉树 然而ta死了,ta是$\Theta (n)$的,加上线段树的常数,$T$飞稳 2.线段树套线段树 我尽量画出来... 图中每个方块是 ...

  2. D. Babaei and Birthday Cake---cf629D(LIS线段树优化)

    题目链接:http://codeforces.com/problemset/problem/629/D 题意就是现有n个蛋糕,蛋糕的形状是圆柱体,每个蛋糕的体积就是圆柱体的体积,每个蛋糕的编号是1-- ...

  3. 二维LIS(CDQ分治)

    题目描述 给定一个长度为N的序列S,S的每个元素pi是一个二元组(xi,yi),定义pi<pj当且仅当xi<xj并且yi<yj,求S的最长上升子序列长度 输入格式 第一行一个N,表示 ...

  4. HDU 1160 FatMouse's Speed(要记录路径的二维LIS)

    FatMouse's Speed Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  5. BZOJ2244: [SDOI2011]拦截导弹(CDQ分治,二维LIS,计数)

    Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高 ...

  6. (转载)Android项目实战(二十八):Zxing二维码实现及优化

    Android项目实战(二十八):Zxing二维码实现及优化   前言: 多年之前接触过zxing实现二维码,没想到今日项目中再此使用竟然使用的还是zxing,百度之,竟是如此牛的玩意. 当然,项目中 ...

  7. 【bzoj3939】[Usaco2015 Feb]Cow Hopscotch 动态开点线段树优化dp

    题目描述 Just like humans enjoy playing the game of Hopscotch, Farmer John's cows have invented a varian ...

  8. hdu 3698 UVA1490 Let the light guide us 线段树优化DP

    题目链接 and 题目大意 hdu3698 但是 hdu的数据比较弱,所以在这luogu提交吧UVA1490 Let the light guide us 有一个\(n*m\)的平原,要求每行选一个点 ...

  9. UVA-1322 Minimizing Maximizer (DP+线段树优化)

    题目大意:给一个长度为n的区间,m条线段序列,找出这个序列的一个最短子序列,使得区间完全被覆盖. 题目分析:这道题不难想,定义状态dp(i)表示用前 i 条线段覆盖区间1~第 i 线段的右端点需要的最 ...

随机推荐

  1. net core 接受post值

    public static string GetPostParams(HttpContext context) { string param = string.Empty; if (context.R ...

  2. CDOJ 1146 A - 秋实大哥与连锁快餐店 最小生成树 Prim算法 稠密图

    题目链接 A - 秋实大哥与连锁快餐店 Time Limit:3000MS     Memory Limit:65535KB     64bit IO Format:%lld & %llu S ...

  3. luogu P1083 借教室 x

    P1083 借教室 题目描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借 ...

  4. windows10 gcc编译C程序(分步编译)

    下面演示gcc对C源程序的分步编译过程: 1. 编译(Compile) gcc hello.cpp -c # 生成hello.o,目标文件名字和源文件名字一样,VC编译会生成.ojb文件,gcc编译器 ...

  5. sh_09_print函数的结尾

    sh_09_print函数的结尾 # 在默认情况下,print 函数输出内容之后,会自动在内容末尾增加换行 print("*", end="---") prin ...

  6. Selenium 详解xpath定位

    xpath定位在业界被戏称为元素定位的"屠龙宝刀",宝刀在手,武林我有.现在我们就来详解xpath定位方法. 一.xpath通过元素属性定位 xpath可以通过元素的属性来定位,如 ...

  7. 2019 南京网络赛A

    南京网络赛自闭现场 https://nanti.jisuanke.com/t/41298 二维偏序经典题型 二维前缀和!!! #include<bits/stdc++.h> using n ...

  8. EM 算法资料

    EM 算法的英文全称是: Expectation-Maximum. EM 算法的步骤 假设 \(Z\) 是隐变量,\(\theta\) 是待定参数. E 步:固定参数 \(\theta\),求 \(Z ...

  9. linux下挂载磁盘

    1.使用fdisk 查看硬盘信息 [root@localhost ~]# fdisk -l Disk /dev/sdb: 107.4 GB, 107374182400 bytes 255 heads, ...

  10. Tomcat中出现"RFC 7230 and RFC 3986"错误的解决方法

    在用axios从前台向后台发请求时,后台报错 Invalid character found in the request target. The valid characters are defin ...