标签:
1 3 0 0 2
Case #1: 1 1 2HintIn the sample, we add three numbers to the sequence, and form three sequences. a. 1 b. 2 1 c. 2 1 3
2010 ACM-ICPC Multi-University Training Contest(13)——Host by UESTC
http://acm.split.hdu.edu.cn/showproblem.php?pid=3564
题意 把1~N个数依次插入相应的位置 有个地方恶心 如样例把1放到0位置 再把2放到0位置 1就必须相应的往后面挪
显然后面插入的大数优先级高 用线段树数空格的方法从后往前插入
最后把得到一个排好的序列 如果用普通的最长上升子序列的方法应该会超时 n*n/2
看了一下大神的 很巧妙吧 http://blog.csdn.net/libin56842/article/details/13095801
每次放的都是一个大于以前所有数的数者这样LiS必然大于等于以前 就看它在什么位置了
如果在len后面必然增加一
#include<stdio.h> #include<algorithm> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define MAX 100010 int tree[MAX*4],a[MAX],ans[MAX],dp[MAX]; int len; //ans[i] 记录是的i的位置ans[i] void pushup(int rt) { tree[rt]=tree[rt<<1]+tree[rt<<1|1]; } void build(int l,int r,int rt) { if(l==r) { tree[rt]=1; return ; } int m=(l+r)>>1; build(lson); build(rson); pushup(rt); } void update(int p,int x,int l,int r,int rt) { if(l==r) { ans[x]=l; tree[rt]=0; return ; } tree[rt]--; //每次消耗一 int m=(l+r)>>1; if(p<=tree[rt<<1]) update(p,x,lson);//左边的位置够就左边 else { p=p-tree[rt<<1]; //不够就到右边相应的位置去找 update(p,x,rson); } } int fan(int k) { int l=1,r=len,mid; while(l<=r) { mid=(l+r)>>1; if(k>dp[mid]) l=mid+1; else r=mid-1; } return l; } int main() { int t,i,n,k,tt; scanf("%d",&t); tt=1; while(t--) { scanf("%d",&n); for(i=1; i<=n; i++) { scanf("%d",&a[i]); dp[i]=0; a[i]++; } build(1,n,1); for(i=n; i>0; i--) update(a[i],i,1,n,1);//数空位线段树 len=0; printf("Case #%d:\n",tt++); for(i=1; i<=n; i++) { k=fan(ans[i]); len=max(len,k); dp[k]=ans[i]; printf("%d\n",len); } printf("\n"); } return 0; }
标签:
原文地址:http://blog.csdn.net/xky140610205/article/details/52259879