• 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
    ",ans);
    //      printf("%d
    ",ans);
        }return 0;
    }
    

      

  • 相关阅读:
    常用经典SQL语句
    怎样找到PB打包所需要的dll和pbd文件?
    C#多线程参数传递
    Sqlserver 常用日期时间函数
    SQL Server:如何判断变量或字段是否为NULL
    用c#开发可供PB调用的COM组件
    ROW_NUMBER() OVER函数的基本用法用法
    SQL Server数据导入导出工具BCP详解
    IE下 Window.Open(url,name), name参数空格、符号问题
    数据库设计系列[05]多公司加入权限系统
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/6721234.html
Copyright © 2020-2023  润新知