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 线段的右端点需要的最 ...
随机推荐
- docker跨主机通信-overlay
使用consul 1,让两个网络环境下的容器互通,那么必然涉及到网络信息的同步,所以需要先配置一下consul. 直接运行下面命令.启动consul. docker run -d -p 8500:85 ...
- js 获取 URL的参数 session
<script type="text/javascript"> window.onload = function () { //var content = getPar ...
- windows 环境如何启动 redis ?
1.cd 到 redis 的安装目录 C:\Users\dell>cd C:\redis 2.执行 redis 启动命令 C:\redis>redis-server.exe redis.w ...
- BZOJ 3786: 星系探索 ETT
Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...
- MongoDB操作:flush()
flush() 是把缓冲区的数据强行输出,(注意不要和frush()刷新混淆了). 主要用在IO中,即清空缓冲区数据,一般在读写流(stream)的时候,数据是先被读到了内存中,再把数据写到文件中,当 ...
- (51)LINUX应用编程和网络编程之六Linux高级IO
3.6.1.非阻塞IO 3.6.1.1.阻塞与非阻塞 阻塞:阻塞具有很多优势(是linux系统的默认设置),单路IO的时候使用阻塞式IO没有降低CPU的性能 补充:阻塞/非阻塞, 它们是程序在等待消息 ...
- linux系统安装Oracle11g详细步骤
快速安装指引 ■Reviewing Information About This Guide■Logging In to the System as root 以root用户登录系统■Checking ...
- wannafly 练习赛11 E 求最值(平面最近点对)
链接:https://www.nowcoder.com/acm/contest/59/E 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K 64bit ...
- [LeetCode]-011-Longest Common Prefix
Write a function to find the longest common prefix string amongst an array of strings. []=>" ...
- WebView:是应用程序打开web网页的UI控件后端
public class WebViewActivity extends Activity { private WebView webView; @Override protected void on ...