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. BZOJ 3398: [Usaco2009 Feb]Bullcow 牡牛和牝牛 水题~

    水~ #include <cstdio> #define N 100004 #define mod 5000011 #define setIO(s) freopen(s".in& ...

  2. luogu P1141 01迷宫 x

    P1141 01迷宫 题目描述 有一个仅由数字0与1组成的n×n格迷宫.若你位于一格0上,那么你可以移动到相邻4格中的某一格1上,同样若你位于一格1上,那么你可以移动到相邻4格中的某一格0上. 你的任 ...

  3. Shell 变量/echo命令

    Shell 教程 Shell 是一个用C语言编写的程序,它是用户使用Linux的桥梁.Shell既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序,这个应用程序提供了一个界面,用户 ...

  4. 一个强大的json解析工具类

    该工具类利用递归原理,能够将任意结构的json字符串进行解析.当然,如果需要解析为对应的实体对象时,就不能用了 package com.wot.cloudsensing.carrotfarm.util ...

  5. mac osx终端批量删除文件

    sudo su cd / find ./ -name "*.html" -exec rm -rf {} \;  注意 {}和\;之间有空格 find [目录名] -name &qu ...

  6. ERROR 1044 (42000): Access denied for user ''@'localhost' to database 'ambari'

    配置Ambari远程maridb 报错: ERROR 1044 (42000): Access denied for user ''@'localhost' to database 'ambari' ...

  7. ArrayList类源码浅析(二)

    1.removeAll(Collection<?> c)和retainAll(Collection<?> c)方法 第一个是从list中删除指定的匹配的集合元素,第二个方法是用 ...

  8. Cannot connect to the Docker daemon. Is 'docker daemon' running on this host?

    if first time to install docker, be noted the docker engine started as root copied from: http://blog ...

  9. ffplay播放PCM裸流

    ffplay -f s16le -ar 48000 -ac 2 d:\lei.pcm

  10. a = a + b 与 a += b 的区别

    1.对于同样类型的a,b来说 两个式子执行的结果确实没有什么区别.但是从编译的角度看吧(武让说的),a+=b;执行的时候效率高. 2.对于不同类型的a,b来说 2.1    不同类型的两个变量在进行运 ...