zoukankan      html  css  js  c++  java
  • luoguP5666 树的重心 树状数组

    这道题在家里仔细想想还是挺好想的...

    考场的时候还是要镇定,给每道题要安排足够的思考时间. 

    code: 

    #include <cstdio> 
    #include <cstring> 
    #include <vector>
    #include <string>   
    #include <algorithm>  
    #define N 500004
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;  
    int n;   
    namespace BIT
    {    
        int C[N]; 
        int lowbit(int t) { return t&(-t); }     
        void clr() { for(int i=0;i<N;++i) C[i]=0; }
        void update(int x,int v) 
        { 
            if(x<=0) return; 
            while(x<N) C[x]+=v,x+=lowbit(x);   
        }   
        int ask(int x) 
        {     
            int re=0; 
            for(int i=x;i>0;i-=lowbit(i))  re+=C[i]; 
            return re; 
        }
        int query(int l,int r) 
        {
            l=max(1,l),r=min(r,n);      
            return l>r?0:ask(r)-ask(l-1);   
        } 
    }; 
    struct node
    {     
        int id,size;     
        node(int id=0,int size=0):id(id),size(size){}  
    };   
    ll ans;   
    vector<node>G[N];    
    bool cmp(node a,node b) { return a.size>b.size; }    
    int edges,cnt_max,det,cn;       
    int hd[N],to[N<<1],nex[N<<1],size[N<<1],st[N],ed[N],cn_nd[N],ori[N];       
    void addedge(int u,int v) 
    {
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;   
    }
    void clr() 
    {
        int i,j; 
        BIT::clr();      
        for(i=1;i<=n;++i) G[i].clear();   
        for(i=0;i<=edges;++i) to[i]=nex[i]=0; 
        for(i=0;i<N;++i) hd[i]=size[i]=ori[i]=cn_nd[i]=0;        
        n=edges=ans=0;    
    }     
    void dfs(int u,int ff) 
    {
        size[u]=1,st[u]=++cn;  
        for(int i=hd[u];i;i=nex[i]) 
        {
            int v=to[i];   
            if(v==ff) continue;     
            dfs(v,u);  
            size[u]+=size[v];   
            G[u].push_back(node(v,size[v]));    
        }     
        ed[u]=cn;   
        if(ff)  G[u].push_back(node(ff,n-size[u]));    
        sort(G[u].begin(),G[u].end(),cmp);          
    }
    void calc_max(int u,int ff) 
    {          
        size[u]=1;          
        for(int i=hd[u];i;i=nex[i]) 
        {
            int v=to[i]; 
            if(v==ff) continue;    
            calc_max(v,u);    
            size[u]+=size[v];  
        } 
        if(size[u]<=det) ++cnt_max;           
    }
    void calc_sec(int u,int ff) 
    {
        size[u]=1;                      
        int flag=G[u][0].id==ff?-1:1;  
        if(G[u].size()==1) G[u].push_back(node(0,0));         
        // if(u==3) printf("qaq  %d %d
    ",2*G[u][0].size-n,n-2*G[u][1].size);                                        
        for(int i=hd[u];i;i=nex[i]) 
        {
            int v=to[i]; 
            if(v==ff) continue;            
            int de=0;                                        
            de-=BIT::query(2*G[u][0].size-n,n-2*G[u][1].size);           
            // 计算子树    
            calc_sec(v,u),size[u]+=size[v];    
            // 计算完毕    
            de+=BIT::query(2*G[u][0].size-n,n-2*G[u][1].size);     
    
            if(flag==-1) 
            {    
                cn_nd[u]-=de;    
            }  
            else
            {
                if(v==G[u][0].id) cn_nd[u]=de;           
            }
        }              
        BIT::update(size[u],1);   
    }
    void dfs_sec(int u,int ff) 
    {       
        BIT::update(size[u],-1);     
        BIT::update(n-size[u],1);   
        if(G[u][0].id==ff)  
        {
            // printf("qaq
    "); 
            cn_nd[u]+=BIT::query(2*G[u][0].size-n,n-2*G[u][1].size);               
            // printf("qaq
    "); 
        }
        for(int i=hd[u];i;i=nex[i]) 
        {
            int v=to[i];   
            if(v==ff) continue;          
            dfs_sec(v,u);      
        }
        BIT::update(size[u],1);   
        BIT::update(n-size[u],-1); 
    }
    void work() 
    { 
        int i,j; 
        clr();   
        scanf("%d",&n); 
        for(i=1;i<n;++i) 
        {
            int x,y; 
            scanf("%d%d",&x,&y);   
            addedge(x,y),addedge(y,x);  
        }
        dfs(1,0);       
        // 计算由最大儿子的贡献   
        for(i=1;i<=n;++i) 
        {     
            if(G[i][0].size*2<=n) 
            {         
                cnt_max=0;  
                det=n-G[i][0].size*2;  
                for(j=1;j<G[i].size();++j)                        
                    calc_max(G[i][j].id,i);    
                ans+=(ll)i*cnt_max;    
                ori[i]+=cnt_max;  
            }
        }
        // 计算次大儿子的贡献   
        calc_sec(1,0);        
        dfs_sec(1,0);     
        ans=0;  
        for(i=1;i<=n;++i) ans+=(ll)i*(ori[i]+cn_nd[i]);  
        printf("%lld
    ",ans); 
    }
    int main() 
    { 
        // setIO("input");     
        int i,j,T; 
        scanf("%d",&T); 
        while(T--) work();   
        return 0;
    } 
    

      

  • 相关阅读:
    RPMBUILD源码打包资源汇总(转)
    grep命令:查看配置文件未注释行(转)
    数据结构实验之查找三:树的种类统计(SDUT 3375)
    数据结构实验之查找三:树的种类统计(SDUT 3375)
    数据结构实验之查找四:二分查找(SDUT 3376)
    数据结构实验之查找五:平方之哈希表 (SDUT 3377)
    数据结构实验之查找一:二叉排序树 (SDUT 3373)
    python 正则表达式
    python #!/usr/bin/python 的作用
    欢迎使用CSDN的markdown编辑器
  • 原文地址:https://www.cnblogs.com/guangheli/p/12234694.html
Copyright © 2011-2022 走看看