【可持久化平衡树】LOJ#6109

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

猜你喜欢

转载自www.cnblogs.com/PsychicBoom/p/11920705.html