优秀的性质:从 (1) 到 (n) 依次插入,所以我们每次只用在比当前位置靠前的所有 (f[i]) 中取个 (max) 然后 (+1) ;我们可以用 平衡树 模拟这个过程。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
} const int N=100010;
int n,tot,rt;
int ch[N][2],sz[N],vl[N],pos[N],f[N],dat[N];
#define ls(x) (ch[x][0])
#define rs(x) (ch[x][1])
inline int cre(int v,int p) {
R tr=++tot;
dat[tr]=rand(),sz[tr]=1,vl[tr]=f[pos[tr]=p]=v;
return tr;
}
inline void upd(int tr) {
sz[tr]=sz[ls(tr)]+sz[rs(tr)]+1;
vl[tr]=max(f[pos[tr]],max(vl[ls(tr)],vl[rs(tr)]));
}
inline void split(int tr,int& x,int& y,int k) {
if(!tr) return x=y=0,void();
if(sz[ls(tr)]<k) x=tr,split(rs(tr),rs(x),y,k-sz[ls(tr)]-1);
else y=tr,split(ls(tr),x,ls(y),k);
upd(tr);
}
inline int merge(int x,int y) {
if(!x||!y) return x+y;
if(dat[x]<dat[y]) {
rs(x)=merge(rs(x),y),upd(x);
return x;
} ls(y)=merge(x,ls(y)),upd(y);
return y;
}
inline void main() {
n=g(); srand(20040109);
for(R i=1,v,x,y,z;i<=n;++i) {
v=g();
split(rt,x,y,v),
z=cre(vl[x]+1,i);
x=merge(x,z);
rt=merge(x,y);
printf("%d
",vl[rt]);
}
}
} signed main() {Luitaryi::main(); return 0;}
2020.01.19