• 牛客网 272B Xor Path(树上操作)


    题目链接:Xor Path

    题意:每个顶点的点权为Ai,任意两点路径上点权异或和为Path(i,j),求所有Path(i,j)和。

    题解:考虑每个顶点被用到的次数,分以下三种情况:

    1.本身和其他顶点:n-1

    2.该顶点上面的顶点(k)和下面的顶点(m)通过该点进行连接:k*m

    3.该顶底下面的顶点通过该点进行连接(上面顶点不用的原因是:从上层层下来,已经记录过。):任意两个子树个数相乘之和。

    第三种情况直接算会超时,我们需要优化一下,考虑下如果子树个数为偶数相当于没有贡献,所以只要考虑子树个数为奇数的即可,最后判断下C(cnt,2)是否为奇数,奇数的话贡献+1。

     1 #include <cstdio>
     2 #include <vector>
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 const int N=5e5+10;
     7 int a[N],ans=0;
     8 ll sz[N],n;
     9 vector <int> E[N];
    10 
    11 void dfs(int u,int fa){
    12     sz[u]=1;
    13     ll sum=0,cnt=0;
    14     for(int i=0;i<E[u].size();i++){
    15         int v=E[u][i];
    16         if(v!=fa){
    17             dfs(v,u);
    18             sz[u]+=sz[v];
    19             if(sz[v]%2==1) cnt++;
    20         }
    21     }
    22     //第三种情况
    23     if((cnt*(cnt-1)/2)%2) sum++;
    24     //n-1为第一种情况,(sz[u]-1)*(n-sz[u])为第二种情况.
    25     sum=(sum+(n-1)+(sz[u]-1)*(n-sz[u])%2)%2;
    26     if(sum%2==1) ans^=a[u];
    27 }
    28 
    29 int main(){
    30     scanf("%d",&n);
    31     for(int i=1;i<n;i++){
    32         int u,v;
    33         scanf("%d%d",&u,&v);
    34         E[u].push_back(v);
    35         E[v].push_back(u);
    36     }
    37     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    38     dfs(1,0);
    39     printf("%d
    ",ans);
    40     return 0;
    41 }
    View Code
  • 相关阅读:
    最长公共前缀
    罗马数字转整数
    回文数
    整数反转
    Linux内核设计与实现——进程管理
    技术派-常用的一些VS相关的宏名
    假如面试3道小学数学题,你可否会?
    技术派-不用sqrt手工计算平方根
    观察者-学历差距造成的差距有多大
    10G文件如何对里面单词出现排序
  • 原文地址:https://www.cnblogs.com/pavtlly/p/10046959.html
Copyright © 2020-2023  润新知