Description
给定一个序列,初始为空。现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置。每插入一个数字,我们都想知道此时最长上升子序列长度是多少?
第一行一个整数N,表示我们要将1到N插入序列中,接下是N个数字,第k个数字Xk,表示我们将k插入到位置Xk(0<=Xk<=k-1,1<=k<=N)
N行,第i行表示i插入Xi位置后序列的最长上升子序列的长度是多少。
100%的数据 n<=100000
Solution
由于每次插入的数字递增,可知插入数字不影响先前答案
用splay模拟插入得到最终序列,然后倒着删数字记录答案即可
似乎也可以用线段树模拟插入,没写
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int INF=0x3f3f3f3f;
const int N=500005;
struct treeNode {
int son[2],fa,size,num;
} t[N];
int a[N],f[N],s[N];
int ans[N],tot,root;
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void push_up(int now) {
t[now].size=t[t[now].son[0]].size+t[t[now].son[1]].size+1;
}
void rotate(int x) {
int y=t[x].fa; int z=t[y].fa;
int k=t[y].son[1]==x;
t[z].son[t[z].son[1]==y]=x; t[x].fa=z;
t[y].son[k]=t[x].son[!k]; t[t[x].son[!k]].fa=y;
t[y].fa=x; t[x].son[!k]=y;
push_up(y); push_up(x);
}
void splay(int x,int goal) {
while (t[x].fa!=goal) {
int y=t[x].fa; int z=t[y].fa;
if (z!=goal) {
if ((t[y].son[1]==x)^(t[z].son[1]==y)) rotate(x);
else rotate(y);
}
rotate(x);
}
if (!goal) root=x;
}
int kth(int k) {
int now=root;
while (233) {
if (t[t[now].son[0]].size+1==k) return now;
if (t[t[now].son[0]].size>=k) {
now=t[now].son[0];
} else {
k-=t[t[now].son[0]].size+1;
now=t[now].son[1];
}
}
}
int main(void) {
freopen("data.in","r",stdin);
freopen("myp.out","w",stdout);
int n=read();
t[1].son[1]=2; t[2].fa=1; t[1].size=2; t[2].size=1;
tot=2; root=1;
rep(i,1,n) {
int k=read();
int l=kth(k+1),r=kth(k+2);
splay(l,0); splay(r,l);
t[r].son[0]=++tot;
t[tot].fa=r; t[tot].size=1;
t[tot].num=i;
push_up(r);
splay(tot,0);
}
rep(i,1,n) s[i]=INF;
rep(i,1,n) {
a[i]=kth(i+1);
a[i]=t[a[i]].num;
int l=0,r=n,ret=0;
while (l<=r) {
int mid=(l+r)>>1;
if (s[mid]>=a[i]) r=mid-1;
else l=mid+1,ret=mid;
}
f[i]=ret+1;
s[f[i]]=std:: min(s[f[i]],a[i]);
ans[a[i]]=f[i];
}
rep(i,1,n) {
ans[i]=std:: max(ans[i],ans[i-1]);
printf("%d\n", ans[i]);
}
return 0;
}