BZOJ[3159]决战 LCT

只有前四个操作的话就是LCT裸题了
链翻转不也是LCT的基本操作吗....
等等,翻转的是权值?
正常的翻转改的是各个点的深度,位置与权值的对应关系并没有改变
那么我们可以考虑维护两棵LCT,一棵维护形态,一棵维护位置
翻转其中一个就相当于改变了对应关系
说的不是很明白的啊....还是看看学姐的blog

代码如下:

#include<ctype.h>
#include<cstdio>
#define int long long
#define INF 2147483647000000l
#define N 50020
using namespace std;
typedef long long LL;
inline int read(){
    int x=0,f=1;char c;
    do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));
    do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));
    return x*f;
}
inline int Max(int a,int b){return a>b?a:b;}
inline int Min(int a,int b){return a<b?a:b;}
inline int max3(int a,int b,int c){return Max(a,Max(b,c));}
inline int min3(int a,int b,int c){return Min(a,Min(b,c));}
int n,m,root,x,y,k,top;
int fir[N];
char c[13];
struct Edge{
    int to,nex;
    Edge(){}
    Edge(int _,int __):to(_),nex(__){}
}nex[N<<1];
inline void add(int x,int y){
    nex[++top]=Edge(y,fir[x]);
    fir[x]=top;
}
struct Node{
    Node *ch[2],*fa,*nex;
    int sum,minn,maxx,addv,x,siz;
    bool rev;
    Node();
    inline void Pushdown();
    inline void Add(int);
    inline void Reverse();
    inline void maintain(){
        minn=min3(ch[0]->minn,ch[1]->minn,x);
        maxx=max3(ch[0]->maxx,ch[1]->maxx,x);
        sum=ch[0]->sum+ch[1]->sum+x;
        siz=ch[0]->siz+ch[1]->siz+1;
        return;
    }
    inline int dir(){
        if(fa->ch[0]==this) return 0;
        if(fa->ch[1]==this) return 1;
        return -1;
    }
}*null,*p[N];
inline void Swap(Node *&a,Node *&b){static Node *c;c=a;a=b;b=c;}
Node::Node(){
    x=addv=minn=maxx=sum=rev=0;
    siz=1;
    ch[0]=ch[1]=nex=fa=null;
    return;
}
inline void Node::Pushdown(){
    if(addv){
        ch[0]->Add(addv);
        ch[1]->Add(addv);
    }
    if(rev) ch[0]->Reverse(),ch[1]->Reverse();
    if(nex!=null){
        if(ch[0]!=null) ch[0]->nex=nex;
        if(ch[1]!=null) ch[1]->nex=nex;
    }
    addv=rev=0;
}
inline void Node::Add(int k){
    if(this==null) return;
    addv=addv+k;sum=sum+k*siz;
    x+=k;minn+=k;maxx+=k;
    return;
}
inline void Node::Reverse(){
    if(this==null) return;
    Swap(ch[0],ch[1]);
    rev=!rev;
    return;
}
inline void init(){
    null=new Node;
    null->ch[0]=null->ch[1]=null->fa=null->nex=null;
    null->sum=null->x=null->siz=null->addv=null->rev=0;
    null->minn=INF;null->maxx=-INF;
    return;
}
void PushUp(Node *x){
    if(~x->dir()) PushUp(x->fa);
    x->Pushdown();
    return;
}
inline Node *K_th(Node *x,int k){
    if(x==null) return x;
    x->Pushdown();
    if(x->ch[0]->siz+1==k)
        return x;
    if(k<=x->ch[0]->siz) return K_th(x->ch[0],k);
    else return K_th(x->ch[1],k-x->ch[0]->siz-1);
}
inline void Rotate(Node *x,int d){
    static Node *k;
    static int di;
    k=x->ch[d^1];
    x->ch[d^1]=k->ch[d];
    if(x->ch[d^1]!=null) x->ch[d^1]->fa=x;
    k->ch[d]=x;
    if(~(di=x->dir())) x->fa->ch[di]=k;
    k->fa=x->fa;x->fa=k;
    x->maintain();k->maintain();
    return;
}
inline void Splay(Node *x){
    static int d;
    PushUp(x);
    while(~(d=x->dir())){
        if(x->fa->dir()==d)
            Rotate(x->fa->fa,d^1);
        Rotate(x->fa,d^1);
    }
    return;
}
inline void Splay_(Node *x,Node *&y){
    Splay(x);Splay(x->nex);
    y=K_th(x->nex,x->ch[0]->siz+1);
    Splay(y);
    return;
}
void dfs(int x,int fa){
    p[x]=new Node;p[x]->nex=new Node;
    p[x]->fa=p[fa];p[x]->nex->fa=p[fa]->nex;
    for(int i=fir[x];i;i=nex[i].nex){
        if(nex[i].to==fa) continue;
        dfs(nex[i].to,x);
    }
}
inline void Access(Node *x){
    static Node *pre,*pre_,*x_;
    pre=pre_=x_=null;
    while(x!=null){
        Splay_(x,x_);
        x->nex=x_;
        x->ch[1]->nex=x_->ch[1];
        x->ch[1]=pre;x_->ch[1]=pre_;
        pre_->fa=x_;
        x->maintain();x_->maintain();
        pre=x;pre_=x_;
        x=x->fa;
    }
    return;
}
inline void MakeRoot(Node *x){
    static Node *k;
    Access(x);Splay_(x,k);
    x->Reverse();k->Reverse();
    return;
}
inline Node *Extract(Node *x,Node *y){
    static Node *y_;
    MakeRoot(x);
    Access(y);Splay_(y,y_);
    return y_;
}
main(){
    init();
    n=read();m=read();root=read();
    for(register int i=1;i<n;i++){
        x=read();y=read();
        add(x,y);add(y,x);
    }
    p[0]=null;
    dfs(root,0);
    for(register int i=1;i<=m;i++){
        scanf("%s",c+1);
        x=read();y=read();
        if(c[3]=='c') k=read(),Extract(p[x],p[y])->Add(k);
        else if(c[3]=='m') printf("%lld\n",Extract(p[x],p[y])->sum);
        else if(c[3]=='j') printf("%lld\n",Extract(p[x],p[y])->maxx);
        else if(c[3]=='n') printf("%lld\n",Extract(p[x],p[y])->minn);
        else Extract(p[x],p[y])->Reverse();
    }
    return 0;
}

posted @ 2018-03-30 09:18  Duan2baka  阅读(202)  评论(0编辑  收藏  举报