Achen大佬说不要沉迷数据结构否则智商会降低的。
从省选考完后就开始学treap,首先是自己yy了一个打了两百多行,然后debug了2个月还是3个月记不清了。
最后弃疗,去找了网上别人的代码抄了一遍。
noip考完后补常规的一段时间,羡慕Achen能20分钟打出一个treap模板,于是自己也开始走上打板子的不归路。
到了后来可以10分钟左右打出一个结构体版的treap,看了Achen的数组版treap,觉得自己结构体版的太不优秀啦,于是就换成数组版的。
然后现在有几周没有碰过treap,感觉又不会打了。。。。不过还好,大概看一下又想起来了。
先放个板子。
结构体版:
//Serene #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<ctime> using namespace std; const int maxn=100000+10; int n,tot=0,ans1,ans2,root; int aa,ff;char cc; int read() { aa=0;ff=1;cc=getchar(); while((cc<‘0‘||cc>‘9‘)&&cc!=‘-‘) cc=getchar(); if(cc==‘-‘) ff=-1,cc=getchar(); while(cc>=‘0‘&&cc<=‘9‘) aa=aa*10+cc-‘0‘,cc=getchar(); return aa*ff; } struct Node{ int num,rnd,son[2],sum,x; }node[maxn]; void rotate(int &pos,int p) { int s=node[pos].son[p]; node[s].sum=node[pos].sum; node[pos].son[p]=node[s].son[!p]; node[s].son[!p]=pos; node[pos].sum=node[pos].x+node[node[pos].son[0]].sum+node[node[pos].son[1]].sum; pos=s; } void add(int &pos,int x) { if(!pos) { pos=++tot;node[pos].num=x;node[pos].rnd=rand(); node[pos].sum=node[pos].x=1; return ; } node[pos].sum++; if(node[pos].num==x) { node[pos].x++; return; } int p=x>node[pos].num; add(node[pos].son[p],x); if(node[node[pos].son[p]].rnd<node[pos].rnd) rotate(pos,p); } void del(int &pos,int x) { if(!pos) return; if(node[pos].num==x) { if(node[pos].x>1) { node[pos].x--;node[pos].sum--;return; } if(node[pos].son[0]*node[pos].son[1]==0) { pos=node[pos].son[0]+node[pos].son[1]; return; } int p= node[node[pos].son[1]].rnd<node[node[pos].son[0]].rnd; rotate(pos,p); node[pos].sum--; del(node[pos].son[!p],x); } else { node[pos].sum--; if(node[pos].num>x) del(node[pos].son[0],x); else del(node[pos].son[1],x); } } int qrank(int pos,int x) { if(node[pos].num==x) return node[node[pos].son[0]].sum+1; if(node[pos].num>x) return qrank(node[pos].son[0],x); return node[node[pos].son[0]].sum+node[pos].x+qrank(node[pos].son[1],x); } int qnum(int pos,int x) { if(x>node[node[pos].son[0]].sum&&x<=node[node[pos].son[0]].sum+node[pos].x) return node[pos].num; if(x<=node[node[pos].son[0]].sum) return qnum(node[pos].son[0],x); return qnum(node[pos].son[1],x-node[pos].x-node[node[pos].son[0]].sum); } void q1(int pos,int x) { if(!pos) return; if(x>node[pos].num) { ans1=node[pos].num; q1(node[pos].son[1],x); } else q1(node[pos].son[0],x); } void q2(int pos,int x) { if(!pos) return; if(x<node[pos].num) { ans2=node[pos].num; q2(node[pos].son[0],x); } else q2(node[pos].son[1],x); } int main() { srand((unsigned)time(NULL)); n=read(); int opt,x,y; for(int i=1;i<=n;++i) { opt=read();x=read(); if(opt==1) add(root,x); else if(opt==2) del(root,x); else if(opt==3) printf("%d\n",qrank(root,x)); else if(opt==4) printf("%d\n",qnum(root,x)); else if(opt==5) q1(root,x),printf("%d\n",ans1); else q2(root,x),printf("%d\n",ans2); } return 0; }
数组版:
//Serene #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; const int maxn=1e5+10; int n,tot,root,ans; int sum[maxn],num[maxn],rnd[maxn],fx[maxn],son[maxn][2]; int aa,ff;char cc; int read() { aa=0;cc=getchar();ff=1; while(cc<‘0‘||cc>‘9‘) { if(cc==‘-‘) ff=-1; cc=getchar(); } while(cc>=‘0‘&&cc<=‘9‘) aa=aa*10+cc-‘0‘,cc=getchar(); return aa*ff; } void rotate(int &pos,int p) { int s=son[pos][p]; sum[s]=sum[pos]; son[pos][p]=son[s][!p]; son[s][!p]=pos; sum[pos]=sum[son[pos][0]]+sum[son[pos][1]]+fx[pos]; pos=s; } void add(int &pos,int x) { if(!pos) { pos=++tot; num[pos]=x; rnd[pos]=rand(); } sum[pos]++; if(num[pos]==x) { fx[pos]++; return; } int p=x>num[pos]; add(son[pos][p],x); if(rnd[son[pos][p]]<rnd[pos]) rotate(pos,p); } void del(int &pos,int x) { if(!pos) return; if(num[pos]==x) { if(fx[pos]>1) { fx[pos]--; sum[pos]--; return; } if(son[pos][0]*son[pos][1]==0) { pos=son[pos][0]+son[pos][1]; return; } int p=rnd[son[pos][1]]<rnd[son[pos][0]]; rotate(pos,p);sum[pos]--; del(son[pos][!p],x); } else { sum[pos]--; del(son[pos][x>num[pos]],x); } } int qnum(int pos,int x) { if(x>sum[son[pos][0]]&&x<=sum[son[pos][0]]+fx[pos]) return num[pos]; if(x<=sum[son[pos][0]]) return qnum(son[pos][0],x); return qnum(son[pos][1],x-sum[son[pos][0]]-fx[pos]); } int qrank(int pos,int x) { if(x==num[pos]) return sum[son[pos][0]]+1; if(x<num[pos]) return qrank(son[pos][0],x); return sum[son[pos][0]]+fx[pos]+qrank(son[pos][1],x); } void q1(int pos,int x) { if(!pos) return; if(num[pos]<x) ans=num[pos],q1(son[pos][1],x); else q1(son[pos][0],x); } void q2(int pos,int x) { if(!pos) return; if(num[pos]>x) ans=num[pos],q2(son[pos][0],x); else q2(son[pos][1],x); } int main() { srand(1031); n=read(); int op,x; for(int i=1;i<=n;++i) { op=read();x=read(); switch(op) { case 1:add(root,x);break; case 2:del(root,x);break; case 3:printf("%d\n",qrank(root,x));break; case 4:printf("%d\n",qnum(root,x));break; case 5:q1(root,x);printf("%d\n",ans);break; case 6:q2(root,x);printf("%d\n",ans);break; } } return 0; }
而非旋treap支持split和merge很是有趣,这次直接照着Achen的板子学,感受到Achen大佬的数据结构多么优秀。
merge的时候不想用pair然后就乱搞了一搞,调了一阵子,最后强制把代码改成自己的码风。感觉不是很难打。
//Serene #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; #define ll long long #define lc son[pos][0] #define rc son[pos][1] const int maxn=1e5+10,base=28; int n,root,tot,ans; int son[maxn][2],num[maxn],sum[maxn],rnd[maxn]; int aa,ff;char cc; int read() { aa=0;ff=1;cc=getchar(); while(cc!=‘-‘&&(cc<‘0‘||cc>‘9‘)) cc=getchar(); if(cc==‘-‘) ff=-1,cc=getchar(); while(cc>=‘0‘&&cc<=‘9‘) aa=aa*10+cc-‘0‘,cc=getchar(); return aa*ff; } void ud(int pos){sum[pos]=sum[lc]+sum[rc]+1;} ll pr(int x,int y) {return ((ll)x<<base)+(ll)y;}//第一个ll要套在里面 int fi(ll x){return x>>base;} int se(ll x){return x-((ll)fi(x)<<base);} int merge(int x,int y) { if((ll)x*y==0) return x^y; if(rnd[x]<rnd[y]) return son[x][1]=merge(son[x][1],y),ud(x),x; else return son[y][0]=merge(x,son[y][0]),ud(y),y; } ll split(int pos,int x) { if(!pos) return 0; ll rs; if(sum[lc]>=x) { rs=split(lc,x); lc=se(rs); rs=pr(fi(rs),pos); } else { rs=split(rc,x-sum[lc]-1); rc=fi(rs); rs=pr(pos,se(rs)); } return ud(pos),rs; } int qrank(int pos,int x) { if(!pos) return 1; if(num[pos]<x) return sum[lc]+1+qrank(rc,x); return qrank(lc,x); } int qnum(int pos,int x) { if(x==sum[lc]+1) return num[pos]; if(x<=sum[lc]) return qnum(lc,x); return qnum(rc,x-sum[lc]-1); } void q1(int pos,int x) { if(!pos) return; if(num[pos]<x) ans=num[pos],q1(son[pos][1],x); else q1(son[pos][0],x); } void q2(int pos,int x) { if(!pos) return; if(num[pos]>x) ans=num[pos],q2(son[pos][0],x); else q2(son[pos][1],x); } void add(int &pos,int x) { int k=qrank(pos,x); ++tot; num[tot]=x;sum[tot]=1;rnd[tot]=rand(); ll p=split(pos,k-1); pos=merge(fi(p),tot); pos=merge(pos,se(p)); } void del(int &pos,int x) { int k=qrank(pos,x); ll p=split(pos,k-1); ll q=split(se(p),1); pos=merge(fi(p),se(q)); } int main() { srand(1031);n=read(); int op,x; while(n--) { op=read(); x=read(); switch(op) { case 1:add(root,x);break; case 2:del(root,x);break; case 3:printf("%d\n",qrank(root,x));break; case 4:printf("%d\n",qnum(root,x));break; case 5:q1(root,x);printf("%d\n",ans);break; case 6:q2(root,x);printf("%d\n",ans);break; } } return 0; }
原文地址:https://www.cnblogs.com/Serene-shixinyi/p/8110765.html
时间: 2024-10-10 04:25:15