题目大意:给定一个序列,依次将1~n插入,问每次插入之后序列的LIS长度是多少
由于是从小到大插入,因此插入一个数之后显然是不影响之前的答案的
因此我们不妨先用平衡树搞出插入之后的序列,再求一遍LIS即可
注意最后每个点还要对前面的取一下max 因为插入后LIS可能还是之前的序列
蒟蒻的我到底还是把平衡树写挂了。。。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 100100 using namespace std; int n,a[M],ans[M]; namespace Treap{ struct abcd{ abcd *ls,*rs; int val,key,size; abcd(int x); void Maintain(); }*null=new abcd(0),*root=null; abcd :: abcd(int x) { ls=rs=null; val=x; key=rand()*(bool)x; size=(bool)x; } void abcd :: Maintain() { size=ls->size+rs->size+1; } void Zig(abcd *&x) { abcd *y=x->ls; x->ls=y->rs; y->rs=x; x=y; x->rs->Maintain(); } void Zag(abcd *&x) { abcd *y=x->rs; x->rs=y->ls; y->ls=x; x=y; x->ls->Maintain(); } void Insert(abcd *&x,int y,int z) { if(x==null) { x=new abcd(z); return ; } if(y<=x->ls->size) { Insert(x->ls,y,z); if(x->ls->key>x->key) Zig(x); } else { Insert(x->rs,y-x->ls->size-1,z); if(x->rs->key>x->key) Zag(x); } x->Maintain(); } void Output(abcd *x) { static int cnt; if(x==null) return ; Output(x->ls); a[++cnt]=x->val; Output(x->rs); } } namespace BIT{ int c[M]; void Update(int x,int y) { for(;x<=n;x+=x&-x) c[x]=max(c[x],y); } int Get_Ans(int x) { int re=0; for(;x;x-=x&-x) re=max(re,c[x]); return re; } } int main() { using namespace Treap; using namespace BIT; int i,x; cin>>n; for(i=1;i<=n;i++) { scanf("%d",&x); Insert(root,x,i); } Output(root); for(i=1;i<=n;i++) { int temp=Get_Ans(a[i])+1; Update(a[i],temp); ans[a[i]]=temp; } for(i=1;i<=n;i++) ans[i]=max(ans[i],ans[i-1]); for(i=1;i<=n;i++) printf("%d\n",ans[i]); return 0; }
时间: 2024-10-18 03:10:52