可持久化平衡树基于fhq-treap实现也可以用有旋treap可是我不会,可持久化把每次merge,split,pushdown涉及到的节点都开个新点继承一下
因为可持久化了所以二操作split完不用merge回去
然后在一篇博客里学习了不记随机权值的fhq-treap写法,看代码趴
#include <bits/stdc++.h> #define N 35100000 #define ll long long #define For(i,x,y) for(int i=(x);i<=(y);++i) using namespace std; int rt,cnt=0,a,b,c,d,e,f,g,h; struct node{ ll val,sum;int sz,ch[2],tag; } t[N]; inline int Rand(){ return (1ll*rand()*rand()%INT_MAX+rand())%INT_MAX; } int newnode(int x){ t[++cnt].val=x,t[cnt].sz=1,t[cnt].sum=x; t[cnt].ch[0]=t[cnt].ch[1]=t[cnt].tag=0; return cnt; } void pushup(int o){ t[o].sz=t[t[o].ch[0]].sz+t[t[o].ch[1]].sz+1; t[o].sum=t[t[o].ch[0]].sum+t[t[o].ch[1]].sum+t[o].val; } void pushd(int o,int x){ t[o].sum+=t[o].sz*x; t[o].tag+=x,t[o].val+=x; } void PushD(int o){ if(!t[o].tag) return; if(t[o].ch[0]){ int p=++cnt;t[p]=t[t[o].ch[0]],t[o].ch[0]=p; pushd(p,t[o].tag); } if(t[o].ch[1]){ int p=++cnt;t[p]=t[t[o].ch[1]],t[o].ch[1]=p; pushd(p,t[o].tag); } t[o].tag=0; } void Split(int o,int k,int &x,int &y){ if(!o) return x=y=0,void(); PushD(o); if(t[t[o].ch[0]].sz>=k){ y=++cnt; t[y]=t[o]; Split(t[o].ch[0],k,x,t[y].ch[0]); pushup(y); } else{ x=++cnt; t[x]=t[o]; Split(t[o].ch[1],k-t[t[o].ch[0]].sz-1,t[x].ch[1],y); pushup(x); } } void merge(int &o,int x,int y){ if(!x || !y){ o=++cnt; return t[o]=t[x+y],void(); } if(Rand()%(t[x].sz+t[y].sz)<t[x].sz){ o=x,PushD(x); merge(t[o].ch[1],t[o].ch[1],y); } else{ o=y,PushD(y); merge(t[o].ch[0],x,t[o].ch[0]); } pushup(o); } void Merge(int &o,int x,int y){ if(!x || !y){ return o=x+y,void(); } if(Rand()%(t[x].sz+t[y].sz)<t[x].sz){ PushD(x); o=++cnt,t[o]=t[x],x=o; Merge(t[o].ch[1],t[o].ch[1],y); } else{ PushD(y); o=++cnt,t[o]=t[y],y=o; Merge(t[o].ch[0],x,t[o].ch[0]); } pushup(o); } void insert(int x){ int p=newnode(x); merge(rt,rt,p); } void Cpy(int l,int r,int len){ a=b=c=d=e=f=g=h=0; Split(rt,l-1,a,b); Split(b,len,c,d); Split(rt,r-1,e,f); Split(f,len,g,h); Merge(e,e,c); Merge(rt,e,h); } void Add(int l,int r,int x){ a=b=c=0; Split(rt,l-1,a,b); Split(b,r-l+1,c,d); t[c].tag+=x,t[c].sum+=t[c].sz*x,t[c].val+=x; Merge(b,c,d); Merge(rt,a,b); } void Qry(int l,int r){ a=b=c=d=0; Split(rt,l-1,a,b); Split(b,r-l+1,c,d); printf("%lld\n",t[c].sum); } int main(){ srand(20031209); int n,m,x,op,l,r; scanf("%d%d",&n,&m); scanf("%d",&x);rt=newnode(x); For(i,2,n) scanf("%d",&x),insert(x); while(m--){ scanf("%d%d%d",&op,&l,&r); if(op==3) Qry(l,r); else{ scanf("%d",&x); if(op==1) Add(l,r,x); else x++,Cpy(l,r,x); } } }