【bzoj 4530】大融合(LCT维护子树信息)

传送门biu~
用LCT维护子树信息。
LCT维护子树信息(子树信息LCT) LCT维护边权(边权LCT) 知识点讲解
xsiz代表节点的虚儿子的size和。
rsiz代表该点在Splay中的size加上该点的xsiz。
每次maintain操作可以更新节点的rsiz值。
增加一个update函数来实现实儿子到虚儿子的转化(改变节点xsiz值),在Access和Link这两个改变边的虚实关系的函数中调用。

#include
using namespace std;
struct Node{
    Node *ch[2],*fa;
    bool rev_mark;
    int rsiz,xsiz;
    Node();
    inline int dir(){
        if(fa->ch[0]==this) return 0;
        if(fa->ch[1]==this) return 1;
        return -1;
    }
    inline void rev(){rev_mark^=1;}
    inline void update(Node *o,int d){xsiz+=d*o->rsiz;}
    inline void pushdown(){
        if(!rev_mark)   return;
        swap(ch[0],ch[1]);
        ch[0]->rev();
        ch[1]->rev();
        rev_mark=false;
    }
    inline void maintain(){rsiz=ch[0]->rsiz+ch[1]->rsiz+xsiz+1;}
}*null=new Node,p[100005];
Node :: Node(){
    ch[0]=ch[1]=fa=null;
    rev_mark=false;
    rsiz=1;
    xsiz=0;
}
void To_pushdown(Node *o){
    if(~o->dir())  To_pushdown(o->fa);
    o->pushdown();
}
inline void Rotate(Node *o,int d){
    Node *p=o->ch[d^1];
    p->ch[d]->fa=o; o->ch[d^1]=p->ch[d];
    p->ch[d]=o;
    o->maintain(); p->maintain();
    if(~o->dir())  o->fa->ch[o->dir()]=p;
    p->fa=o->fa; o->fa=p;
}
inline void Splay(Node *o){
    To_pushdown(o);
    while(~o->dir()){
        if(o->dir()==o->fa->dir())  Rotate(o->fa->fa,o->dir()^1);
        Rotate(o->fa,o->dir()^1);
    }
}
inline void Access(Node *o){
    Node *p=null;
    while(o!=null){
        Splay(o);
        o->update(o->ch[1],1);  o->update(p,-1);
        o->ch[1]=p;     o->maintain();
        p=o;
        o=o->fa;
    }
}
inline void Move_to_root(Node *o){
    Access(o);  Splay(o);
    o->rev();
}
inline void Link(Node *x,Node *y){
    Move_to_root(x);
    Move_to_root(y);
    x->fa=y; y->update(x,1);
}
inline long long Query(Node *x,Node *y){
    Move_to_root(x);
    Access(y);  Splay(y);
    return 1ll*x->rsiz*(y->xsiz+1);
}
int main(){
    null->rsiz=0;
    int n,T;
    scanf("%d%d",&n,&T);
    while(T--){
        char opt[2];int x,y;
        scanf("%s%d%d",opt,&x,&y);
        if(opt[0]=='A') Link(&p[x],&p[y]);
        else            printf("%lld\n",Query(&p[x],&p[y]));
    }
    return 0;
}

你可能感兴趣的:(~bzoj,树,———LCT,zP1nG的bzoj)