【题解】
离线处理:
由于仅含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; }