Codeforces 766E

题意:给一棵树(1e5),每个节点上有对应权值(0<=ai<=1e6)定义树上两个节点间的距离为路径中节点的异或,求所有节点对间的距离和(包括节点自身也作为节点对,距离为节点权值)。

解题思路:

  做了771C后这道题就有感觉了。关键在于将每个权值的二进制位拆开计算,以dp[u][i][0]和dp[u][i][1]记录到达节点u的子树上的节点的距离的第 i 位为0和1的个数有多少,维护计算就可以了。比较僵的是开始写的时候没有考虑单独一个节点作为一个节点对,所以在每个递归的最后面单独加上到全局变量res中。

  每一个递归的最开始,用局部变量num数组记录u的权值的二进制形式,同时初始化dp[u]数组。对每个子节点的遍历转移:

  先递归子节点,返回后则已计算完毕。则有如果u的第 i 位为1,dp[u][i][1]+=dp[v][i][0], dp[u][i][0]+=dp[v][i][1]; 否则dp[u][i][1]+=dp[v][i][1], dp[u][i][0]+=dp[v][i][0]; 这里应该不难理解。

  至于统计答案,只计算为1的即可,即int cnt1=dp[u][i][1]*dp[v][i][0]+dp[u][i][0]*dp[v][i][1]; res+=1LL*cnt1*(1<<i); 

  见代码:(转移其实比771C好写一点感觉)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
#define sqr(x) ((x)*(x))
const int N=1e5+10,M=21;
int head[N],nxt[N<<1],to[N<<1],cnt;
int n,a[N],dp[N][M][2];
ll res;
void init(){
    memset(head,-1,sizeof(head));
    res=cnt=0;
}
void addEdge(int u,int v){
    nxt[cnt]=head[u];
    to[cnt]=v;
    head[u]=cnt++;
}
void dfs(int u,int pre){
    int num[M];
    for(int i=0;i<M;i++){
        if(a[u]&(1<<i)) num[i]=1,dp[u][i][1]=1,dp[u][i][0]=0;
        else num[i]=0,dp[u][i][1]=0,dp[u][i][0]=1;
    }
    for(int e=head[u];~e;e=nxt[e]){
        int v=to[e];
        if(v==pre) continue;
        dfs(v,u); 
        for(int i=0;i<M;i++){
            int cnt1=dp[u][i][1]*dp[v][i][0]+dp[u][i][0]*dp[v][i][1];
            res+=1LL*cnt1*(1<<i);
            if(num[i]){
                dp[u][i][1]+=dp[v][i][0];
                dp[u][i][0]+=dp[v][i][1];
            }else{
                dp[u][i][1]+=dp[v][i][1];
                dp[u][i][0]+=dp[v][i][0];
            }
        }
    }
    res+=a[u];
}
int main(){
    //freopen("in.txt","r",stdin);
    while(~scanf("%d",&n)){
        for(int i=1;i<=n;i++)
            scanf("%d",a+i);
        init();
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            addEdge(u,v);
            addEdge(v,u);
        }
        dfs(1,0);
        printf("%I64d\n",res);
    }
    return 0;
}

 

posted @ 2017-03-23 15:16  轶辰  阅读(289)  评论(0编辑  收藏  举报