【BZOJ】3159决战-LCT

题解

此题的一种经典做法:套两颗LCT,一颗维护权值,一颗维护形态。
形态树里的每一个节点都有一个对应的权值树里的点。
对于值的区间翻转,只翻转权值树。其他操作则两棵树一起操作。
在形态树中操作时,对于节点之间关系的修改,对应权值中的点可以通过bst找k大完成。

代码

#include<cstdio>
 #include<algorithm>
 #include<cstring> 
 #include<cctype>
 #include<cstdlib>
 using namespace std;
 typedef long long ll;
 const int N=5e4+10;
 const ll inf=1LL<<60;
 int n,m,R;
 char s[12];

 inline int rd()
 {
    char ch=getchar();int x=0,f=1;
    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
    return x*f;
 }

 struct Ta{
    struct Node{
        Node *ch[2],*f;int sz,rv;
        ll ad,v,mn,mx,sum;
        void reverse(){
            rv^=1;swap(ch[0],ch[1]);
        }
        void update(){
            sz=ch[0]->sz+1+ch[1]->sz;
            sum=ch[0]->sum+v+ch[1]->sum;
            mn=min(min(ch[0]->mn,ch[1]->mn),v);
            mx=max(max(ch[0]->mx,ch[1]->mx),v); 
        } 
        void change(int w){
            ad+=w;v+=w;mn+=w;mx+=w;sum+=1ll*sz*w; 
        }
        void pushdown(Node *null){
            if(rv){
                if(ch[0]!=null) ch[0]->reverse();
                if(ch[1]!=null) ch[1]->reverse();
                rv=0; 
            }
            if(ad){
                if(ch[0]!=null) ch[0]->change(ad);
                if(ch[1]!=null) ch[1]->change(ad);
                ad=0; 
            }
        }
    }*null,t[N];
    Ta(){null=t;null->f=null->ch[0]=null->ch[1]=null;null->ad=null->sz=null->sum=0;null->mn=inf;null->mx=-inf;}
    void rotate(Node *x){
        if(x==null || x->f==null) return;Node *y=x->f;Node *z=y->f;
        int s= y->ch[1]==x,gs= z->ch[1]==y;x->f=z; 
        if(z!=null) z->ch[gs]=x; 
        y->ch[s]=x->ch[s^1];x->ch[s^1]->f=y;x->ch[s^1]=y;y->f=x;y->update();x->update();
    }
    Node *sta[N];
    void splay(Node *x){
       Node *y=x;int top=0;
       while(y!=null) {sta[++top]=y;y=y->f;}
       for(int i=top;i;i--) sta[i]->pushdown(null);
       while(x->f!=null){
          if(x->f->f==null) rotate(x);
          else {
            (x->f->f->ch[1]==x->f)^(x->f->ch[1]==x) ?rotate(x):rotate(x->f);rotate(x);
          }
       } 
    } 
    Node* kth(Node *x,int k){
       if(x->sz<k) return null;
       Node *y=x;
       while(k){
          y->pushdown(null);
          if(y->ch[0]->sz+1==k) break;
          y->ch[0]->sz>=k? y=y->ch[0]:(k-=(y->ch[0]->sz+1),y=y->ch[1]);
       }
       splay(y);return y;
    }
 }Val;

 struct Tb{
    struct Node{
        Node *ch[2],*p,*f;Ta:: Node *val;
        int rv,sz;
        void reverse(){
            rv^=1;swap(ch[0],ch[1]);
        }
        void update(){
            sz=ch[0]->sz+1+ch[1]->sz;
        }
        void pushdown(Node *null){
            if(rv){
                if(ch[0]!=null) ch[0]->reverse();
                if(ch[1]!=null) ch[1]->reverse();
                rv=0;
            }
        }
    }*null,t[N];
    Tb(){null=t;null->ch[0]=null->ch[1]=null->p=null->f=null;null->sz=0;}
    void rotate(Node *x){
        if(x==null || x->f==null) return;Node *y=x->f;Node *z=y->f;
        int s= y->ch[1]==x,gs= z->ch[1]==y;x->f=z; 
        if(z!=null) z->ch[gs]=x; 
        y->ch[s]=x->ch[s^1];x->ch[s^1]->f=y;x->ch[s^1]=y;y->f=x;y->update();x->update();
        swap(x->p,y->p);swap(x->val,y->val);//
    }
    Node *sta[N];
    void splay(Node *x){
       Node *y=x;int top=0;
       while(y!=null) {sta[++top]=y;y=y->f;}
       for(int i=top;i;i--) sta[i]->pushdown(null);
       while(x->f!=null){
          if(x->f->f==null) rotate(x);
          else {
            (x->f->f->ch[1]==x->f)^(x->f->ch[1]==x) ?rotate(x):rotate(x->f);rotate(x);
          }
       } 
    } 
    Node *access(Node *x){
        Node *y=null;int k;
        Ta:: Node *q,*e;
        while(x!=null){
            splay(x);
           if(x->ch[1]!=null){
              k=x->ch[0]->sz+2;
              q=Val.kth(x->val,k);
              Val.splay(q);
              e=q->ch[0];
              x->ch[1]->val=q;x->ch[1]->f=null;x->ch[1]->p=x;
              q->ch[0]->f=Val.null;q->ch[0]=Val.null;q->update();
              Val.splay(x->val=e);
           }
           if(y!=null){
              k=x->val->sz;
              q=Val.kth(x->val,k);
              Val.splay(q);
              q->ch[1]=y->val;q->ch[1]->f=q;q->update();
              Val.splay(x->val);
           }
           x->ch[1]=y;y->p=null;y->f=x;x->update();
           y=x;x=x->p;
        } 
        return y;
    }
    void mkrt(Node *x){
        Node *y=access(x);
        y->reverse();y->val->reverse();
    }
    void lk(Node *x,Node *y){
        mkrt(x);splay(x);x->p=y;access(x);
    }
    void rev(Node *x,Node *y){
        mkrt(x);
        access(y)->val->reverse();
    }
    void Add(Node *x,Node *y,int w){
        mkrt(x);
        access(y)->val->change(w);
    }
    ll Qsum(Node *x,Node *y){
        mkrt(x);
        return access(y)->val->sum;
    }
    ll Qmax(Node *x,Node *y){
        mkrt(x);
        return access(y)->val->mx;
    }
    ll Qmin(Node *x,Node *y){
        mkrt(x);
        return access(y)->val->mn;
    }
 }Lct;
 Ta :: Node *B[N];
 Tb :: Node *A[N];

 int main(){
    int i,j,x,y,z;
    n=rd();m=rd();R=rd();
    for(i=1;i<=n;++i) B[i]=Val.t+i;
    for(i=1;i<=n;++i){
        A[i]=Lct.t+i;A[i]->f=A[i]->p=A[i]->ch[0]=A[i]->ch[1]=Lct.null;
        A[i]->val=Val.t+i;A[i]->sz=1;A[i]->val->sz=1;
        A[i]->val->f=A[i]->val->ch[0]=A[i]->val->ch[1]=Val.null;
    }
    for(i=1;i<n;++i){x=rd();y=rd();Lct.lk(A[x],A[y]);}
    while(m--){
        scanf("%s",s);x=rd();y=rd();
        if(s[0]=='I' && s[2]=='c'){z=rd();Lct.Add(A[x],A[y],z);} 
        else if(s[0]=='S') printf("%lld\n",Lct.Qsum(A[x],A[y]));
        else if(s[0]=='M' && s[1]=='a') printf("%lld\n",Lct.Qmax(A[x],A[y]));
        else if(s[0]=='M' && s[1]=='i') printf("%lld\n",Lct.Qmin(A[x],A[y]));
        else Lct.rev(A[x],A[y]); 
    }
 }

猜你喜欢

转载自blog.csdn.net/corsica6/article/details/80672502