[LCT维护树的权值与形态]BZOJ3159.决战

题解可以看Manchery博客

分不清左右儿子的我……

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

typedef long long ll;

const int N=50010;

struct VT{
    struct NODE{
        NODE *ch[2],*f;
        ll add,mx,mn,sum,rev,size,w;

        void set(int x){
            ch[0]=ch[1]=f=0;
            add=rev=0; mx=mn=sum=w=x; size=1;
        }

        void Reverse(){
            rev^=1;
        }

        void Add(ll x){
            add+=x; mx+=x; mn+=x; sum+=size*x; w+=x;
        }

        void Push(){
            if(add){
                if(ch[0]) ch[0]->Add(add);
                if(ch[1]) ch[1]->Add(add);
                add=0;
            }
            if(rev){
                swap(ch[0],ch[1]);
                if(ch[0]) ch[0]->Reverse();
                if(ch[1]) ch[1]->Reverse();
                rev=0;
            }
        }

        void Up(){
            size=1; mx=mn=sum=w;
            if(ch[0]) 
                size+=ch[0]->size,mx=max(mx,ch[0]->mx),mn=min(mn,ch[0]->mn),sum+=ch[0]->sum;
            if(ch[1]) 
                size+=ch[1]->size,mx=max(mx,ch[1]->mx),mn=min(mn,ch[1]->mn),sum+=ch[1]->sum;
        }
    }a[N];

    void rot(NODE *x){
        NODE *y=x->f,*z=y->f; int wh=y->ch[1]==x;
        if(z) z->ch[z->ch[1]==y]=x; x->f=z;
        if(y->ch[wh]=x->ch[wh^1]) y->ch[wh]->f=y;
        (x->ch[wh^1]=y)->f=x; y->Up(); x->Up();
    }

    void PUSHTOP(NODE *x){
        if(x->f) PUSHTOP(x->f);
        x->Push();
    }

    void splay(NODE *x){
        PUSHTOP(x);
        while(x->f){
            NODE *y=x->f;
            if(y->f && (y->f->ch[1]==y)==(y->ch[1]==x)) rot(y);
            rot(x);
        }
    }

    int Size(NODE *x){
        if(!x) return 0;
        return x->size;
    }

    NODE *find_kth(NODE *rt,int k){
        NODE *x=rt;
        if(x->size<k) return 0;
        while(1){
            x->Push();
            if(Size(x->ch[0])+1==k) return x;
            if(Size(x->ch[0])>=k) x=x->ch[0];
            else k-=Size(x->ch[0])+1,x=x->ch[1];
        }
        return x;
    }
}T1;

typedef VT::NODE* P;

struct LINKCUTTREE{
    struct NODE{
        NODE *ch[2],*f; P val;
        int rev,size;
        void Up(){
            size=1;
            if(ch[0]) size+=ch[0]->size;
            if(ch[1]) size+=ch[1]->size;
        }
        void Push(){
            if(!rev) return ;
            swap(ch[0],ch[1]);
            if(ch[0]) ch[0]->rev^=1;
            if(ch[1]) ch[1]->rev^=1;
            rev=0;
        }
    }a[N];

    void set(int x,int y){
        a[x].ch[0]=a[x].ch[1]=a[x].f=0;
        a[x].rev=0; (a[x].val=T1.a+x)->set(y);
    }

    int isl(NODE *x){
        return !x->f || (x->f->ch[0]!=x && x->f->ch[1]!=x);
    }

    int isr(NODE *x){
        return x->f && x->f->ch[1]==x;
    }

    void rot(NODE *x){
        NODE *y=x->f,*z=y->f; int wh=isr(x);
        if(!isl(y)) z->ch[z->ch[1]==y]=x; x->f=z;
        if(y->ch[wh]=x->ch[wh^1]) y->ch[wh]->f=y;
        (x->ch[wh^1]=y)->f=x; y->Up(); x->Up();
        swap(x->val,y->val);
    }

    void PUSHTOP(NODE *x){
        if(!isl(x)) PUSHTOP(x->f);
        x->Push();
    }

    void splay(NODE *x){
        PUSHTOP(x);
        for(;!isl(x);rot(x))
            if(!isl(x->f)) rot(isr(x->f)^isr(x)?x:x->f);
    }

    int Size(NODE *x){
        return !x?0:x->size;
    }

    void access(NODE *x){
        NODE *lst=0;
        while(x){
            splay(x);
            if(x->ch[1]){
                int rk=Size(x->ch[0])+2;
                P t=T1.find_kth(x->val,rk);
                T1.splay(t);
                x->val=t->ch[0]; x->ch[1]->val=t; x->ch[1]=0;
                t->ch[0]->f=0; t->ch[0]=0; t->Up();
                T1.splay(x->val);
            }
            if(lst){
                P t=T1.find_kth(x->val,x->val->size);
                T1.splay(t);
                t->ch[1]=lst->val; lst->val->f=t; t->Up();
                lst->val=0;
                x->ch[1]=lst; 
                T1.splay(x->val);
            }
            lst=x; x->Up(); x=x->f;
        }
    }

    void reverse(NODE *x){
        access(x); splay(x); x->rev^=1; x->val->Reverse();
    }

    void link(int x,int y){
        reverse(a+x); 
        reverse(a+y); 
        a[x].f=a+y; 
        access(a+x);
    }

    ll Qmax(int x,int y){
        reverse(a+x); access(a+y); splay(a+y); return (a+y)->val->mx;
    }

    ll Qmin(int x,int y){
        reverse(a+x); access(a+y); splay(a+y); return (a+y)->val->mn;
    }

    ll Qsum(int x,int y){
        reverse(a+x); access(a+y); splay(a+y); return (a+y)->val->sum;
    }

    void Add(int x,int y,int z){
        reverse(a+x); access(a+y); splay(a+y); (a+y)->val->Add(z);
    }

    void Rev(int x,int y){
        reverse(a+x); access(a+y); splay(a+y); (a+y)->val->Reverse();
    }
}LCT;

int n,m,r;

char opt[10];

int main(){
    freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
    scanf("%d%d%d",&n,&m,&r);
    for(int i=1;i<=n;i++) LCT.set(i,0);
    for(int i=1,x,y;i<=n-1;i++)
        scanf("%d%d",&x,&y),LCT.link(x,y);
    for(int i=1,x,y,w;i<=m;i++){
        scanf("%s %d%d",opt,&x,&y);
        if(!strcmp(opt,"Increase"))
            scanf("%d",&w),LCT.Add(x,y,w);
        else if(!strcmp(opt,"Sum"))
            printf("%lld\n",LCT.Qsum(x,y));
        else if(!strcmp(opt,"Major"))
            printf("%lld\n",LCT.Qmax(x,y));
        else if(!strcmp(opt,"Minor"))
            printf("%lld\n",LCT.Qmin(x,y));
        else LCT.Rev(x,y);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值