首页 > 代码库 > ACdream 1216 (ASC训练1) Beautiful People(DP)
ACdream 1216 (ASC训练1) Beautiful People(DP)
题目地址:http://acdream.info/problem?pid=1216
这题一开始用的是线段树,后来发现查询的时候还需要DP处理,挺麻烦。。也就不了了之了。。后来想到,这题其实就是一个二维的最长上升子序列。。
要先排序,先按左边的数为第一关键字进行升序排序,再按右边的数为第二关键字进行降序排序。这样的话,第一关键字相同的的肯定不在一个同一个上升子序列中。然后只对第二关键字进行复杂度为O(n*logn)的DP,找出最长上升序列,然后处理前驱,并输出即可。
代码如下:
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <map> #include <set> #include <algorithm> using namespace std; #define LL long long struct node { int x, y, num; }fei[110000]; int cmp(node x, node y) { if(x.x==y.x) return x.y>y.y; return x.x<y.x; } int a[110000], d[110000], pre[110000], len, b[110000]; int bin_seach(int x) { int low=0, high=len, mid, ans; while(low<=high) { mid=low+high>>1; if(a[mid]>=x) { high=mid-1; ans=mid; } else { low=mid+1; } } return ans; } int main() { int n, i, j, pos, cnt; while(scanf("%d",&n)!=EOF) { for(i=0;i<n;i++) { scanf("%d%d",&fei[i].x,&fei[i].y); fei[i].num=i+1; } sort(fei,fei+n,cmp); len=1; a[1]=fei[0].y; d[0]=-1; d[1]=0; memset(pre,-1,sizeof(pre)); for(i=1;i<n;i++) { if(fei[i].y>a[len]) { a[++len]=fei[i].y; pre[i]=d[len-1]; d[len]=i; } else { pos=bin_seach(fei[i].y); a[pos]=fei[i].y; pre[i]=d[pos-1]; d[pos]=i; } } printf("%d\n",len); cnt=0; /*for(i=0;i<n;i++) { printf("%d ",fei[i].num); } puts("");*/ for(i=d[len];i!=-1;i=pre[i]) { b[cnt++]=fei[i].num; //printf("%d\n",i); } for(i=0;i<cnt-1;i++) printf("%d ",b[i]); printf("%d\n",b[cnt-1]); } return 0; }
ACdream 1216 (ASC训练1) Beautiful People(DP)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。