题意:写一个数据结构,要求滋兹两种操作,ADD:插入一个数,GET:令$i++$然后输出第$i$小的数
这个数据结构当然是平衡树啦!(雾)
写个Treap直接过掉啦…
#include<cstdio> #include<cstdlib> typedef long long lint; const int N=200005; inline lint read() { lint s=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){s=s*10+c-'0';c=getchar();} return s*f; } struct Treap { lint v; int l,r,w,rnd,s; }tr[N]; int n,m,cnt; int f[N],a[N]; inline void updata(int x) { tr[x].s=tr[tr[x].l].s+tr[tr[x].r].s+tr[x].w; } inline void rturn(int &x) { int t=tr[x].l;tr[x].l=tr[t].r;tr[t].r=x; tr[t].s=tr[x].s;updata(x);x=t; } inline void lturn(int &x) { int t=tr[x].r;tr[x].r=tr[t].l;tr[t].l=x; tr[t].s=tr[x].s;updata(x);x=t; } inline void insert(int &k,lint val) { if(k==0) { k=++cnt;tr[k].v=val; tr[k].s=tr[k].w=1;tr[k].rnd=rand(); return; } tr[k].s++; if(tr[k].v==val) tr[k].w++; else if(tr[k].v<val) { insert(tr[k].r,val); if(tr[tr[k].r].rnd<tr[k].rnd)lturn(k); }else { insert(tr[k].l,val); if(tr[tr[k].l].rnd<tr[k].rnd)rturn(k); } } inline void query(int k,int val,int &ans) { if(k==0)return; if(val<=tr[tr[k].l].s) query(tr[k].l,val,ans); else if(tr[tr[k].l].s+tr[k].w<val) query(tr[k].r,val-tr[tr[k].l].s-tr[k].w,ans); else ans=k; } int main() { int x,k=0,rot=0;m=read();n=read(); for(register int i=1;i<=m;i++)a[i]=read(); for(register int i=1;i<=n;i++)x=read(),f[x]++; for(register int i=1;i<=m;i++) { insert(rot,a[i]); while(f[i]--) { int ans;query(rot,++k,ans); printf("%lld ",tr[ans].v); } } return 0; }
正解应该是对顶堆…我好像不会做…