BZOJ1500: [NOI2005]维修数列(平衡树)

传送门
题意:
平衡树的一系列操作。

题解:
Splay/无旋Treap
Splay:

#include<bits/stdc++.h>
using namespace std;
struct IO{
    streambuf *ib,*ob;
    inline void init(){
        ios::sync_with_stdio(false);
        cin.tie(NULL);cout.tie(NULL);
        ib=cin.rdbuf();ob=cout.rdbuf();
    }
    inline int read(){
        char ch=ib->sbumpc();int i=0,f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();}
        while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=ib->sbumpc();}
        return i*f;
    }
    inline void W(long long x){
        static int buf[50];
        if(!x){ob->sputc('0');ob->sputc('\n');return;}
        if(x<0){ob->sputc('-');x=-x;}
        while(x)buf[++buf[0]]=x%10,x/=10;
        while(buf[0])ob->sputc(buf[buf[0]--]+'0');
        ob->sputc('\n');
    }
}io;

const int Maxn=5e5+50,INF=0x3f3f3f3f;

int n,m,nowtot;

struct node{
    node *lc,*rc,*fa;
    int val,sum,revtag,addtag,maxx,lmax,rmax,sze,isadd;
    node();
    inline void upt();
    inline void add(int v){
        val=v;sum=v*sze;
        int t=(v>0)?sze:1;
        maxx=lmax=rmax=t*v;
        addtag=v;isadd=1;
    }
    inline void rev(){
        swap(lc,rc);revtag^=1;
        swap(lmax,rmax);
    }
    inline void pushdown();
}Pool[Maxn],*pool=Pool,*null=Pool;
node::node():lc(null),rc(null),val(-INF),maxx(-INF),lmax(-INF),rmax(-INF),isadd(0){}
void node::upt() {
    sum=lc->sum+rc->sum+val;
    lmax=max(lc->lmax,max(lc->sum+val,lc->sum+val+rc->lmax));
    rmax=max(rc->rmax,max(rc->sum+val,rc->sum+val+lc->rmax));
    sze=lc->sze+rc->sze+1;
    maxx=max(val+max(lc->rmax,0)+max(rc->lmax,0),max(lc->maxx,rc->maxx));
}
void node::pushdown(){
    if(revtag){
        revtag=0;
        if(lc!=null)lc->rev();
        if(rc!=null)rc->rev();
    }
    if(isadd){
        if(lc!=null)lc->add(addtag);
        if(rc!=null)rc->add(addtag);
        isadd=0;
    }
}
struct RecyclePool{
    node *que[Maxn];
    int tail;
    inline node* newnode(int val){
        static node* tmp;
        tmp=(tail?que[tail--]:++pool);
        tmp->lc=tmp->rc=tmp->fa=null;tmp->isadd=0;
        tmp->revtag=tmp->addtag=0;tmp->sze=1;
        tmp->val=tmp->sum=tmp->maxx=tmp->lmax=tmp->rmax=val;
        return tmp;
    }
    inline void recycle(node *u){
        if(u==null)return;
        que[++tail]=u;
        recycle(u->lc);recycle(u->rc);
    }
}recyclepool;
struct Splay{
    node *rt;
    inline bool which(node *x){return x->fa->lc==x;}
    inline void rotate(node *x){
        node *y=x->fa,*z=y->fa;
        if(z!=null)(z->lc==y?z->lc:z->rc)=x;
        x->fa=z;y->fa=x;node *b;
        if(y->lc==x){b=x->rc;x->rc=y;y->lc=b;}
        else{b=x->lc;x->lc=y;y->rc=b;}
        if(b)b->fa=y;
        y->upt();x->upt();
    }
    inline void splay(node *x,node *tar){
        static node* que[Maxn];static int tail;
        que[tail=1]=x;
        for(node* y=x;y->fa!=null;y=y->fa)que[++tail]=y->fa;
        for(int i=tail;i>=1;i--)que[i]->pushdown();
        while(x->fa!=tar){
            node *y=x->fa,*z=y->fa;
            if(z!=tar)(which(x)^which(y))?(rotate(x)):(rotate(y));
            rotate(x);
        }
        if(tar==null)rt=x;
    }
    inline void insert(node *&now,node *fa,int pos,int val){
        now->pushdown();
        if(now==null){
            now=recyclepool.newnode(val);now->fa=fa;
            splay(now,null);
            return;
        }
        if(now->lc->sze+1>pos)insert(now->lc,now,pos,val);
        else insert(now->rc,now,pos-now->lc->sze-1,val);
    }
    inline node* findpos(node *now,int pos){
        now->pushdown();
        if(now->lc->sze+1==pos)return now;
        else if(now->lc->sze+1<pos)return findpos(now->rc,pos-now->lc->sze-1);
        else return findpos(now->lc,pos);
    }
    inline int querysum(int l,int r){
        splay(findpos(rt,l),null);splay(findpos(rt,r+2),rt);
        return rt->rc->lc->sum;
    }
    inline void del(int l,int r){
        splay(findpos(rt,l),null);splay(findpos(rt,r+2),rt);
        recyclepool.recycle(rt->rc->lc);rt->rc->lc->fa=null;rt->rc->lc=null;
        rt->rc->upt();rt->upt();
    }
    inline void rev(int l,int r){
        splay(findpos(rt,l),null);splay(findpos(rt,r+2),rt);
        rt->rc->lc->rev();rt->rc->upt();rt->upt();
    }
    inline void add(int l,int r,int v){
        splay(findpos(rt,l),null);splay(findpos(rt,r+2),rt);
        rt->rc->lc->add(v);rt->rc->upt();rt->upt();
    }
    inline node* build(node *fa,int *a,int l,int r){
        int mid=(l+r)>>1;
        node *tmp=recyclepool.newnode(a[mid]);tmp->fa=fa;
        if(l==r)return tmp;
        if(l<mid)tmp->lc=build(tmp,a,l,mid-1);
        if(r>mid)tmp->rc=build(tmp,a,mid+1,r);
        tmp->upt();
        return tmp;
    }
    inline void insert(int pos,int *a,int tot){
        node *tmp=build(null,a,1,tot);
        splay(findpos(rt,pos+1),null);splay(findpos(rt,pos+2),rt);
        tmp->fa=rt->rc;rt->rc->lc=tmp;rt->rc->upt();rt->upt();
    }
}splay;
int a[Maxn];
inline void print(node *now){
    if(now->lc!=null)print(now->lc);
    cout<<now->val<<" ";
    if(now->rc!=null)print(now->rc);
}
int main(){
io.init();n=io.read(),m=io.read();splay.rt=null;nowtot=n;
    splay.insert(splay.rt,null,0,-INF);
    splay.insert(splay.rt,null,1,-INF);
    for(int i=1;i<=n;i++){splay.insert(splay.rt,null,i,io.read());}
    for(int i=1;i<=m;i++){
        static char ch[15];
        cin>>(ch+1);
        if(ch[1]=='G'){
            int pos=io.read(),tot=io.read();
            if(!tot){io.W(0);continue;}
            io.W(splay.querysum(pos,pos+tot-1));
        }
        else if(ch[1]=='M'&&ch[3]=='X'){
            if(!nowtot){io.W(0);continue;}
            io.W(splay.rt->maxx);
        }
        else if(ch[1]=='I'){
            int pos=io.read(),tot=io.read();nowtot+=tot;
            for(int j=1;j<=tot;j++){
                a[j]=io.read();
            }
            splay.insert(pos,a,tot);
        }
        else if(ch[1]=='D'){
            int pos=io.read(),tot=io.read();nowtot-=tot;
            splay.del(pos,pos+tot-1);
        }
        else if(ch[1]=='R'){
            int pos=io.read(),tot=io.read();
            splay.rev(pos,pos+tot-1);
        }
        else{
            int pos=io.read(),tot=io.read(),c=io.read();
            if(!tot)continue;
            splay.add(pos,pos+tot-1,c);        
        }
    }
}

无旋Treap:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned int uint;
struct IO{
    streambuf *ib,*ob;
    inline void init(){
        ios::sync_with_stdio(false);
        cin.tie(NULL);cout.tie(NULL);
        ib=cin.rdbuf();ob=cout.rdbuf();
    }
    inline int read(){
        char ch=ib->sbumpc();int i=0,f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();}
        while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=ib->sbumpc();}
        return i*f;
    }
    inline void W(long long x){
        static int buf[50];
        if(!x){ob->sputc('0');ob->sputc('\n');return;}
        if(x<0){ob->sputc('-');x=-x;}
        while(x)buf[++buf[0]]=x%10,x/=10;
        while(buf[0])ob->sputc(buf[buf[0]--]+'0');
        ob->sputc('\n');
    }
    inline uint unit(){
        static uint status0=23333;
        status0^=status0<<13;
        status0^=status0>>17;
        status0^=status0<<5;
        return status0;
    }
}io;

const int Maxn=5e5+50,INF=0x3f3f3f3f;

int n,m,nowtot;

struct node{
    node *lc,*rc;
    int val,sum,revtag,addtag,maxx,lmax,rmax,sze,isadd;
    uint pri;
    node();
    inline void upt();
    inline void add(int v){
        val=v;sum=v*sze;
        int t=(v>0)?sze:1;
        maxx=lmax=rmax=t*v;
        addtag=v;isadd=1;
    }
    inline void rev(){
        swap(lc,rc);revtag^=1;
        swap(lmax,rmax);
    }
    inline void pushdown();
}Pool[Maxn],*pool=Pool,*null=Pool;
typedef pair<node*,node*> pii;
node::node():lc(null),rc(null),val(-INF),maxx(-INF),lmax(-INF),rmax(-INF),isadd(0), revtag(0){}
void node::upt() {
    sum=lc->sum+rc->sum+val;
    lmax=max(lc->lmax,max(lc->sum+val,lc->sum+val+rc->lmax));
    rmax=max(rc->rmax,max(rc->sum+val,rc->sum+val+lc->rmax));
    sze=lc->sze+rc->sze+1;
    maxx=max(val+max(lc->rmax,0)+max(rc->lmax,0),max(lc->maxx,rc->maxx));
}
void node::pushdown(){
    if(revtag){
        revtag=0;
        if(lc!=null)lc->rev();
        if(rc!=null)rc->rev();
    }
    if(isadd){
        if(lc!=null)lc->add(addtag);
        if(rc!=null)rc->add(addtag);
        isadd=0;
    }
}
struct RecyclePool{
    node *que[Maxn];
    int tail;
    inline node* newnode(int val){
        static node* tmp;
        tmp=(tail?que[tail--]:++pool);
        tmp->lc=tmp->rc=null;tmp->isadd=0;tmp->pri=io.unit();
        tmp->revtag=tmp->addtag=0, tmp->sze=1;
        tmp->val=tmp->maxx=tmp->lmax=tmp->rmax=val;
        return tmp;
    }
    inline void recycle(node *u){
        if(u==null)return;
        que[++tail]=u;
        recycle(u->lc);recycle(u->rc);
    }
}recyclepool;
struct Treap{
    node *rt;
    inline node* merge(node *x,node *y){
        if(x==null)return y;
        if(y==null)return x;
        x->pushdown(), y->pushdown();
        if(x->pri < y->pri){
            x->rc = merge(x->rc, y), x->upt();
            return x;
        }
        else{
            y->lc = merge(x, y->lc), y->upt();
            return y;
        }
    }
    inline pii split(node *u,int k){
        if(u==null) return pii(null, null);
        u->pushdown();
        if (u->lc->sze + 1 <= k){
            pii tr = split(u->rc, k - u->lc->sze - 1);
            u->rc = tr.first, u->upt();
            return pii(u,tr.second);
        }
        else {
            pii tr = split(u->lc,k);
            u->lc = tr.second;u->upt();
            return pii(tr.first,u);
        }
    }
    inline int querysum(int l,int tot){
        pii tr=split(rt,l-1);pii tr2=split(tr.second,tot);
        int ans = tr2.first->sum;
        rt=merge(tr.first,merge(tr2.first,tr2.second));
        return ans;
    }
    inline void del(int l,int tot){
        pii tr=split(rt,l-1);pii tr2=split(tr.second,tot);
        recyclepool.recycle(tr2.first);
        rt=merge(tr.first,tr2.second);
    }
    inline void rev(int l,int tot){
        pii tr=split(rt,l-1);pii tr2=split(tr.second,tot);
        tr2.first->rev();
        rt=merge(tr.first,merge(tr2.first,tr2.second));
    }
    inline void add(int l,int tot,int val){
        pii tr=split(rt,l-1);pii tr2=split(tr.second,tot);
        tr2.first->add(val);
        rt=merge(tr.first,merge(tr2.first,tr2.second));
    }
    inline node* build(int *a,int n){
        static node* st[Maxn],*pre;static int tail;
        tail=0;
        for(int i=0;i<n;i++){
            node *u=recyclepool.newnode(a[i]);pre=null;
            while(tail&&st[tail]->pri>u->pri)
                st[tail]->upt(),pre=st[tail--];
            if(tail)st[tail]->rc=u;
            u->lc=pre;st[++tail]=u;
        }
        while(tail)st[tail--]->upt();
        return st[1];
    }
    inline void insert(int *a, int n, int pos) {
        node *u = build(a, n);
        pii t = split(rt, pos);
        rt = merge(merge(t.first, u), t.second);
    }
}treap;
int a[Maxn];

int main(){
    io.init();n=io.read(),m=io.read();treap.rt=null;nowtot=n;
    for(int i=0;i<n;i++){a[i] = io.read();}
    treap.rt=treap.build(a,n);
    for(int i=1;i<=m;i++){
        static char ch[15];
        cin>>(ch+1);
        if(ch[1]=='G'){
            int pos=io.read(),tot=io.read();
            if(!tot){io.W(0);continue;}
            io.W(treap.querysum(pos,tot));
        }
        else if(ch[1]=='M'&&ch[3]=='X'){
            if(!nowtot){io.W(0);continue;}
            io.W(treap.rt->maxx);
        }
        else if(ch[1]=='I'){
            int pos=io.read(),tot=io.read();nowtot+=tot;
            for(int j=0;j<tot;j++){
                a[j] = io.read();
            }
            treap.insert(a, tot, pos);
        }
        else if(ch[1]=='D'){
            int pos=io.read(),tot=io.read();nowtot-=tot;
            if(!tot)continue;
            treap.del(pos,tot);
        }
        else if(ch[1]=='R'){
            int pos=io.read(),tot=io.read();
            if(!tot)continue;
            treap.rev(pos,tot);
        }
        else{
            int pos=io.read(),tot=io.read(),c=io.read();
            if(!tot)continue;
            treap.add(pos,tot,c);        
        }
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值