首页 > 代码库 > Codeforces:"North-East"
Codeforces:"North-East"
Codeforces:"North-East"
题目链接:http://codeforces.com/gym/101246/problem/H
题目大意:空间内有$n$个点,现取$x$和$y$严格递增的点组成最长序列,问可能取到哪些点,一定取到哪些点.
DP
这道题要求的是二维LIS,可以按$x$递增排序将其降为一维,当横坐标相等时,因为要求坐标严格递增,按$y$递减排序。
从后面往前搞,$maxy[len]$记录LIS长度为$len$的点的最大$y$,若以当前点为结尾的LIS长度为$len$,当前点的$y$小于$maxy[len+1]$则为可能取到的点。
代码如下:
1 #include <cstdio> 2 #include <algorithm> 3 #include <vector> 4 #include <set> 5 #define N 100005 6 using namespace std; 7 struct node{ 8 int x,y,id; 9 friend bool operator<(node a,node b){10 if(a.x==b.x)return a.y>b.y;11 return a.x<b.x;12 }13 }a[N];14 const int inf=1000005;15 int n,dp[N],val[N],k,pos[N],maxy[N];16 vector<int>v[N];17 set<int>A,B;18 void init(){19 freopen("input.txt","r",stdin);20 freopen("output.txt","w",stdout);21 }22 bool cmp(int x,int y){23 return val[x]>val[y];24 }25 void output(){26 printf("%d",A.size());27 for(set<int>::iterator it=A.begin();it!=A.end();++it)28 printf(" %d",*it);29 printf("\n");30 printf("%d",B.size());31 for(set<int>::iterator it=B.begin();it!=B.end();++it)32 printf(" %d",*it);33 printf("\n");34 }35 int main(void){36 init();37 scanf("%d",&n);38 for(int i=0;i<n;++i){39 scanf("%d%d",&a[i].x,&a[i].y);40 a[i].id=i+1;41 }42 sort(a,a+n);43 for(int i=0;i<n;++i){44 int v=a[i].y;45 int t=lower_bound(dp,dp+k,v)-dp;46 dp[t]=v;47 val[a[i].id]=a[i].y;48 pos[a[i].id]=t;49 if(t==k)k++;50 }51 for(int i=0;i<k;++i)52 maxy[i]=-inf;53 maxy[k]=inf;54 for(int i=n-1;i>=0;--i){55 int id=a[i].id;56 int p=pos[id];57 if(val[id]<maxy[p+1]){58 A.insert(id);59 maxy[p]=max(maxy[p],val[id]);60 v[p].push_back(id);61 }62 }63 for(int i=0;i<k;++i)64 if((int)v[i].size()==1)65 B.insert(v[i][0]);66 output();67 }
Codeforces:"North-East"
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。