可持久化平衡树基于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);
}
}
}