首先用平衡树把最后的序列维护出来,然后统计每一位为结尾的LIS长度。然后维护一下答案就好了。
AC代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define N 200005
using namespace std;
int n,cnt,trtot,rt,bit[N],ans[N],a[N],c[N][2],sz[N],rd[N];
void maintain(int k){
sz[k]=sz[c[k][0]]+sz[c[k][1]]+1;
}
void turn(int &k,int l){
int t=c[k][l],r=l^1; c[k][l]=c[t][r]; c[t][r]=k;
maintain(k); maintain(t); k=t;
}
void ins(int &k,int rst){
if (!k){
k=++trtot; sz[k]=1;
rd[k]=rand(); return;
}
sz[k]++;
if (rst>sz[c[k][0]]){
ins(c[k][1],rst-sz[c[k][0]]-1);
if (rd[c[k][1]]>rd[k]) turn(k,1);
} else{
ins(c[k][0],rst);
if (rd[c[k][0]]>rd[k]) turn(k,0);
}
}
void dfs(int x){
if (!x) return;
dfs(c[x][0]); a[++cnt]=x; dfs(c[x][1]);
}
void add(int x,int t){
for (; x<=n; x+=x&-x) bit[x]=max(bit[x],t);
}
int getmax(int x){
int t=0; for (; x; x-=x&-x) t=max(t,bit[x]); return t;
}
int main(){
srand(26501); scanf("%d",&n); int i;
for (i=1; i<=n; i++){
int x; scanf("%d",&x); ins(rt,x);
}
dfs(rt);
for (i=1; i<=n; i++){
ans[a[i]]=getmax(a[i]-1)+1;
add(a[i],ans[a[i]]);
}
for (i=1; i<=n; i++) printf("%d\n",ans[i]=max(ans[i-1],ans[i]));
return 0;
}
by lych
2016.2.23