Description
Solution
哇真的异常服气。。线段树都可以搞合并和拆分的啊orzorz。神的世界我不懂
Code
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; const int M=20000010; const int N=200010; int sz[M],lc[M],rc[M],tag[M],rt[N],all_work,cnt; int _new(int x=1) { int o=++cnt; tag[o]=x-1; sz[o]=1<<tag[o]; lc[o]=rc[o]=0; return cnt; } void pushdown(int o) { if (!tag[o]) return; lc[o]=_new(tag[o]); rc[o]=_new(tag[o]); tag[o]=0; } int split(int o,int k) { int now=++cnt,re=now; pushdown(o); while (lc[o]||rc[o]) { tag[now]=0;sz[now]=k;sz[o]-=k; if (k<=sz[lc[o]]) { lc[now]=_new();rc[now]=0; now=lc[now];o=lc[o]; } else { rc[now]=_new();lc[now]=lc[o]; k-=sz[lc[o]];lc[o]=0; now=rc[now];o=rc[o]; } pushdown(o); } tag[now]=tag[o]=0; sz[now]=k;sz[o]-=k; return re; } int merge(int x,int y) { if (!x||!y) return x+y; lc[x]=merge(lc[x],lc[y]); rc[x]=merge(rc[x],rc[y]); sz[x]+=sz[y]; return x; } int query(int x,int k) { int o=rt[x]; if (x>all_work||k>=sz[o]) return -1; int re=0; while (lc[o]||rc[o]) { re<<=1; if (lc[o]&&k<sz[lc[o]]) o=lc[o]; else k-=sz[lc[o]],re|=1,o=rc[o]; } return re*(1<<tag[o])+k; } int T,n,root; int _type,_k,_i,_p; void clear() { cnt=all_work=0; root=_new(31); } int main() { scanf("%d",&T); while (T--) { clear(); scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%d",&_type); if (_type==1) { scanf("%d",&_k); all_work++; rt[all_work]=0; if (sz[root]<_k) {printf("failed ");continue;} rt[all_work]=split(root,_k); printf("ok "); } if (_type==2) { scanf("%d",&_i); if (_i>all_work||!rt[_i]) {printf("failed ");continue;} root=merge(root,rt[_i]);rt[_i]=0; printf("ok "); } if (_type==3) { scanf("%d%d",&_i,&_p); int ans=query(_i,_p); if (ans!=-1) printf("%d ",ans); else printf("failed "); } } } }