BZOJ 2888: 资源运输

Description

加边,询问连通块中所有点到重心的距离。

Solution

LCT.

http://www.cnblogs.com/clrs97/p/4776809.html

一开始没想到怎么合并两颗树时候计算贡献...

Code

/**************************************************************
    Problem: 2888
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:1560 ms
    Memory:6684 kb
****************************************************************/
 
#include <bits/stdc++.h>
using namespace std;
 
const int N = 100050;
 
int n,q,ans;
 
struct LinkCutTree {
    #define lc(o) ch[o][0]
    #define rc(o) ch[o][1]
     
    int f[N],ch[N][2];
    int sz[N],s[N],a[N],d[N],t[N],tsz[N];
    vector<int> g[N];
     
    void AddEdge(int u,int v) { g[u].push_back(v),g[v].push_back(u); }
    void clr(int o) { sz[o]=tsz[o]=1,f[o]=lc(o)=rc(o)=s[o]=a[o]=d[o]=t[o]=0; }
    int isrt(int o) { return !f[o]||(lc(f[o])!=o&&rc(f[o])!=o); }
    void Tadd(int o,int _a) {
        if(!o) return;
        t[o]+=_a,tsz[o]+=_a;
    }
    void Tadd(int o,int _a,int _d) {
        if(!o) return;
        s[o]+=_a+sz[rc(o)]*_d,a[o]+=_a,d[o]+=_d;
    }
    void Push(int o) {
        if(t[o]) { Tadd(lc(o),t[o]),Tadd(rc(o),t[o]),t[o]=0; }
        if(d[o]) { Tadd(lc(o),a[o]+(sz[rc(o)]+1)*d[o],d[o]),Tadd(rc(o),a[o],d[o]),d[o]=a[o]=0; }
    }
    void Pushdown(int o) { if(!isrt(o)) Pushdown(f[o]);Push(o); }
    void Update(int o) { if(!o) return;sz[o]=sz[lc(o)]+sz[rc(o)]+1; }
    void Rot(int o) {
        int p=f[o],k=f[p],d=rc(p)==o;
        if(!isrt(p)) ch[k][rc(k)==p]=o;
        f[o]=k,f[p]=o,f[ch[o][d^1]]=p;
        ch[p][d]=ch[o][d^1],ch[o][d^1]=p;
        Update(p),Update(o),Update(k);
    }
    void Splay(int o) {
        Pushdown(o);
        for(;!isrt(o);) {
            int p=f[o],k=f[p];
            if(!isrt(p)) Rot((rc(p)==o)==(rc(k)==p)?p:o);
            Rot(o);
        }
    }
    void Access(int o) { for(int v=0;o;o=f[v=o]) Splay(o),rc(o)=v,Update(o); }
    int Getrt(int o) { Access(o),Splay(o);for(;lc(o);o=lc(o));return o; }
    void Addp(int u,int v) {
        clr(v),f[v]=u,tsz[v]=0;
        u=Getrt(u),Access(v),Splay(u),Tadd(u,1),Tadd(u,0,1);
        for(v=rc(u);lc(v);v=lc(v));Splay(v);
        if(2*tsz[v]>tsz[u]) {
            int su=tsz[u],sv=tsz[v];
            tsz[v]=su,tsz[u]-=sv;
            s[u]-=s[v]+sv,s[v]+=s[u]+su-sv;
            Access(v),Splay(u),lc(u)=v,rc(u)=0;
        }
    }
    void DFS(int u,int fa) {
        Addp(fa,u);
        for(int i=0,v;i<(int)g[u].size();i++) if((v=g[u][i])!=fa) 
            DFS(v,u);
    }
    void Link(int u,int v) {
        int ru=Getrt(u),rv=Getrt(v);
        ans-=s[ru]+s[rv];
        if(tsz[ru]<tsz[rv]) swap(u,v);
        DFS(v,u),AddEdge(u,v);
        ans+=s[Getrt(u)];
    }
    void init() { for(int i=1;i<=n;i++) clr(i); }
}py;
 
int main() {
//  freopen("in.in","r",stdin);
    scanf("%d%d",&n,&q);
    py.init();
    for(int i=1;i<=q;i++) {
        char opt[5];int x,y;
        scanf("%s",opt);
        if(*opt=='A') scanf("%d%d",&x,&y),py.Link(x,y);
        else printf("%d\n",ans);
//      printf("%d\n",ans);
    }return 0;
}

  

posted @ 2017-04-17 08:44  北北北北屿  阅读(122)  评论(0编辑  收藏  举报