新学了无旋 treap,感觉特别好用,贴个模板在这里,之后再来补一下理解和注释。
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #define MAXN 100010 using namespace std; int n; struct FhqTree{ int L[MAXN],R[MAXN],val[MAXN],key[MAXN],siz[MAXN]; int cnt,root; int newnode(int data){ val[++cnt]=data; key[cnt]=rand(); siz[cnt]=1; return cnt; } void update(int now){ siz[now]=siz[L[now]]+siz[R[now]]+1; } void split(int now,int data,int &x,int &y){ if(!now) x=y=0; else{ if(val[now]<=data){ x=now; split(R[now],data,R[now],y); } else{ y=now; split(L[now],data,x,L[now]); } update(now); } } int merge(int x,int y){ if(!x||!y) return x+y; if(key[x]>key[y]){ R[x]=merge(R[x],y); update(x); return x; } else{ L[y]=merge(x,L[y]); update(y); return y; } } int x,y,z; void insert(int data){ split(root,data,x,y); root=merge(merge(x,newnode(data)),y); } void erease(int data){ split(root,data,x,z); split(x,data-1,x,y); y=merge(L[y],R[y]); root=merge(merge(x,y),z); } void getrank(int data){ split(root,data-1,x,y); printf("%d ",siz[x]+1); root=merge(x,y); } void getnum(int rank){ int now=root; while(now){ if(siz[L[now]]+1==rank) break; else if(siz[L[now]]>=rank) now=L[now]; else rank-=siz[L[now]]+1,now=R[now]; } printf("%d ",val[now]); } void pre(int data){ split(root,data-1,x,y); int now=x; while(R[now]) now=R[now]; printf("%d ",val[now]); root=merge(x,y); } void nxt(int data){ split(root,data,x,y); int now=y; while(L[now]) now=L[now]; printf("%d ",val[now]); root=merge(x,y); } }fhq; int main(){ srand(time(0)); scanf("%d",&n); int opt,x; while(n--){ scanf("%d%d",&opt,&x); if(opt==1) fhq.insert(x); else if(opt==2) fhq.erease(x); else if(opt==3) fhq.getrank(x); else if(opt==4) fhq.getnum(x); else if(opt==5) fhq.pre(x); else if(opt==6) fhq.nxt(x); } return 0; }
当然也可以用 FhqTreap 解决区间问题, 也就是说可以完成线段数的任务, 虽然会比线段树慢一点, 但也可以做线段树做不到的区间插入
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #define MAXN 200010 using namespace std; typedef long long LL; int n,m; struct FhqTreap{ int L[MAXN],R[MAXN],siz[MAXN],key[MAXN]; LL sum[MAXN],val[MAXN],tag[MAXN]; int cnt,root; int newnode(int value){ siz[++cnt]=1;key[cnt]=rand(); sum[cnt]=value;val[cnt]=value; return cnt; } void pushdown(int id){ sum[L[id]]+=tag[id]*siz[L[id]]; sum[R[id]]+=tag[id]*siz[R[id]]; val[L[id]]+=tag[id];tag[L[id]]+=tag[id]; val[R[id]]+=tag[id];tag[R[id]]+=tag[id]; tag[id]=0; } void pushup(int id){ siz[id]=siz[L[id]]+siz[R[id]]+1; sum[id]=sum[L[id]]+sum[R[id]]+val[id]; } void split(int id,int size,int &x,int &y){ if(!id) x=y=0; else{ if(tag[id]) pushdown(id); if(siz[L[id]]<size){ x=id; split(R[id],size-siz[L[id]]-1,R[id],y); } else{ y=id; split(L[id],size,x,L[id]); } pushup(id); } } int merge(int x,int y){ if(!x||!y) return x+y; if(key[x]>key[y]){ if(tag[x]) pushdown(x); R[x]=merge(R[x],y); pushup(x); return x; } else{ if(tag[y]) pushdown(y); L[y]=merge(x,L[y]); pushup(y); return y; } } void add(int l,int r,LL value){ int x,y,z; split(root,l-1,x,y); split(y,r-l+1,y,z); sum[y]+=value*siz[y]; val[y]+=value; tag[y]+=value; root=merge(merge(x,y),z); } void insert(int pos,int value){ int x,y; split(root,pos-1,x,y); root=merge(merge(x,newnode(value)),y); } void ask(int l,int r){ int x,y,z; split(root,l-1,x,y); split(y,r-l+1,y,z); printf("%lld ",sum[y]); root=merge(merge(x,y),z); } }fhq; int main(){ srand(time(0)); scanf("%d",&n); for(int i=1,x;i<=n;i++){ scanf("%d",&x); fhq.insert(i,x); } scanf("%d",&m); for(int i=1,opt,x,y,z;i<=m;i++){ scanf("%d",&opt); if(opt==1){ scanf("%d",&x); fhq.insert(x,0); } else if(opt==2){ scanf("%d%d%d",&x,&y,&z); fhq.add(x,y,z); } else if(opt==3){ scanf("%d%d",&x,&y); fhq.ask(x,y); } } return 0; }