【題解】
離線處理:
第n個數的插入不會改變前n-1個數的相對位置,因此可以直接求得最終序列,第i次操作的答案就是僅含1~i的LIS
最終序列可以用Treap求得;
由於僅含1~i的LIS = max( 僅含1~i-1的LIS , 以i爲結尾的LIS ),可以用O(N*logN)的動態規劃求出以每個數爲結尾的LIS,再遞推求出每步答案
【代碼】
#include<stdio.h>
#include<stdlib.h>
int a[100005],ans[100005],g[100005];
int n,p=0,p2=0;
int max(int a,int b)
{
if(a>b) return a;
return b;
}
struct Node
{
Node* ch[2];
int v,r,s;
int cmp_s(int x) const
{
if( x <= ch[0]->s + 1 ) return 0;
return 1;
}
};
Node *root,*null;
void init()
{
null=new Node();
null->ch[0] = null->ch[1] = NULL;
null->v=null->r=null->s=0;
root=null;
}
void gets(Node* &o)
{
o->s = o->ch[0]->s + 1 + o->ch[1]->s;
}
void xz(Node* &o,int d)
{
Node* k=o->ch[d^1];
o->ch[d^1]=k->ch[d];
k->ch[d]=o;
gets(o);
gets(k);
o=k;
}
void tj(Node* &o,int x)
{
if(o==null)
{
o=new Node();
o->ch[0] = o->ch[1] = null;
o->v=++p;
o->r=rand();
o->s=1;
return;
}
int d=o->cmp_s(x);
o->s++;
if(d==1) x-= o->ch[0]->s + 1;
tj(o->ch[d],x);
if( o->ch[d]->r < o->r ) xz(o,d^1);
}
void geta(Node* &o)
{
if(o->ch[0]!=null) geta(o->ch[0]);
a[++p2]=o->v;
if(o->ch[1]!=null) geta(o->ch[1]);
}
int find(int num,int left,int right)
{
int mid;
while(left<right)
{
mid=(left+right+1)/2;
if(g[mid]>num) right=mid-1;
else left=mid;
}
return left;
}
int main()
{
srand(25);
int i,x,len=0;
init();
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&x);
tj(root,x+1);
}
geta(root);
for(i=1;i<=n;i++)
{
x=find(a[i],0,len)+1;
ans[a[i]]=x;
g[x]=a[i];
len=max(len,x);
}
for(i=1;i<=n;i++)
{
ans[i]=max(ans[i-1],ans[i]);
printf("%d\n",ans[i]);
}
return 0;
}