BZOJ 4530 [Bjoi2014]大融合 LCT維護子樹信息

題目大意:給出n個點,定義一條邊的負載就是它所在的當前能夠聯通的樹上路過它的簡單路徑的數量,要求支持兩個操作:加邊,詢問邊的負載。保證加邊不會出現環。

暴力用LCT維護子樹信息。

LCT維護子樹信息(子樹信息LCT) LCT維護邊權(邊權LCT) 知識點講解

與普通LCT的區別主要在於maintain函數(更新節點信息)和update函數(虛實邊轉換時更新信息,普通LCT沒有)

siz表示正常Splay的size(然而在這道題裏並沒有什麼卵用)
rsiz(real_size)表示LCT子樹的size和(rsiz=ch[0]->rsiz+ch[1]->rsiz+xsiz+1,注意可能會包括父親的rsiz)
xsiz(虛_size)表示與當前點連虛邊的兒子的LCT子樹size和(用於更新rsiz)

#include <cstdio>
#include <algorithm>
#define N 100005
using namespace std;
typedef long long LL;
struct Node {
    Node *ch[2],*pa;
    int dir() { return pa->ch[0]==this ? 0 : pa->ch[1]==this ? 1 : -1; }
    int siz,xsiz,rsiz;
    bool rev_mark;
    Node();
    void rev();
    void pushdown();
    void maintain();
    void update(Node*,int);
}*null=new Node(),p[N];
Node :: Node():rev_mark(false),xsiz(0) {
    pa=ch[0]=ch[1]=null;
    siz=null?1:0;
    rsiz=siz;
}
void Node :: rev() {
    rev_mark=!rev_mark;
    swap(ch[0],ch[1]);
    return ;
}
void Node :: pushdown() {
    if(rev_mark) {
        ch[0]->rev();
        ch[1]->rev();
        rev_mark=false;
    }
    return ;
}
void Node :: maintain() {
    siz=ch[0]->siz+ch[1]->siz+1;
    rsiz=ch[0]->rsiz+ch[1]->rsiz+1+xsiz;
    return ;
}
void Node :: update(Node* o,int k) {
    xsiz+=k*o->rsiz;
    rsiz+=k*o->rsiz;
    return ;
}
void Rotate(Node* o,int d) {
    Node* k=o->ch[d^1]; int d2;
    o->ch[d^1]=k->ch[d]; k->ch[d]->pa=o;
    k->ch[d]=o;
    o->maintain(), k->maintain();
    if(~(d2=o->dir())) o->pa->ch[d2]=k;
    k->pa=o->pa, o->pa=k;
    return ;
}
void To_pushdown(Node* o) {
    static Node* q[N];
    int top=0;
    while(~(o->dir())) q[++top]=o, o=o->pa;
    q[++top]=o;
    while(top) q[top--]->pushdown();
    return ;
}
void Splay(Node* o) {
    To_pushdown(o);
    int d;
    while(~(d=o->dir())) {
        if(o->pa->dir()==d) Rotate(o->pa->pa,d^1);
        Rotate(o->pa,d^1);
    }
    return ;
}
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->pa;
    }
    return ;
}
void Move_to_root(Node* o) {
    Access(o), Splay(o);
    o->rev();
    return ;
}
void Link(Node* x,Node* y) {
    Move_to_root(x);
    Move_to_root(y);
    x->pa=y;
    y->update(x,1);
    return ;
}
LL query(Node* x,Node* y) {
    Move_to_root(x);
    Access(y), Splay(x);
    return (LL)(x->xsiz+1)*(y->rsiz-x->xsiz-1);
}
int n,T;
int main() {
    scanf("%d",&n);
    for(scanf("%d",&T);T;T--) {
        char mode[3];
        int x,y;
        scanf("%s%d%d",mode,&x,&y);
        if(mode[0]=='A') Link(p+x,p+y);
        else printf("%lld\n",query(p+x,p+y));
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章