【20160815】noip模拟(未完)

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 using namespace std;
  7 
  8 const int N=100010;
  9 int n,m,len;
 10 struct node{
 11     int x,y,d,next;
 12 }a[2*N];
 13 int first[N],f0[N],f1[N][20],g0[N],g1[N][20],tot[N];
 14 /*
 15 若m=0,
 16 f[x]:x的子树的节点到x的距离的总和
 17 g[x]:不是x的子树上的点到x的距离的总和
 18 f[x]=f[y]+d(x,y)*tot[y] y=all son[x]
 19 g[x]=f[fa]+g[fa] - (f[x]+tot[x]*d(x,fa)) + (n-tot[x])*d(x,fa)
 20 
 21 因为m<=15,异或只会影响最后四位数
 22 则将f[x]拆分为f0[x]:f[x]除去最后四位数的部分:xx0000
 23               f1[x][0~15]:f1[x][j]表示f[x]中有多少个最后四位为j的距离(不能像原来一样直接加进去,因为最后要异或)
 24 g[x]同理。
 25 */
 26 
 27 void ins(int x,int y,int d)
 28 {
 29     len++;
 30     a[len].x=x;a[len].y=y;a[len].d=d;
 31     a[len].next=first[x];first[x]=len;
 32 }
 33 
 34 void dfs1(int x,int fa)
 35 {
 36     f1[x][0]=1;//debug
 37     tot[x]=1;
 38     for(int i=first[x];i;i=a[i].next)
 39     {
 40         int y=a[i].y;
 41         if(y!=fa)
 42         {
 43             dfs1(y,x);
 44             tot[x]+=tot[y];
 45             // f[x]+=f[y]+a[i].d*tot[y];
 46             int now=a[i].d;
 47             f0[x]+=f0[y]+tot[y]*(now-(now%16));
 48             for(int j=0;j<=15;j++)
 49             {
 50                 int t=j+now%16;
 51                 f1[x][t%16]+=f1[y][j];
 52                 f0[x]+=(t-(t%16))*f1[y][j];
 53             }
 54         }
 55     }
 56 }
 57 
 58 void dfs2(int x,int fa)
 59 {
 60     for(int i=first[x];i;i=a[i].next)
 61     {
 62         int y=a[i].y;
 63         if(y!=fa)
 64         {
 65             // g[y]=f[x]+g[x]-f[y]+(n-2*tot[y])*a[i].d;
 66             // g[y]=f[x]+g[x] - (f[y]+tot[y]*a[i].d) + (n-tot[y])*a[i].d
 67             
 68             /*
 69             减法不会出现不够减:
 70             因为减的东西之前一定加过(所以要考虑它的实际意义)
 71             */
 72             
 73             //z c  f[y]+tot[y]*a[i].d
 74             int z=0,c[20];
 75             memset(c,0,sizeof(c));
 76             int now=a[i].d;
 77             z+=f0[y]+tot[y]*(now-(now%16));
 78             for(int j=0;j<=15;j++)
 79             {
 80                 int t=j+now%16;
 81                 c[t%16]+=f1[y][j];//以y为根的子树中每个点都要加d(x,y),j变为t%16
 82                 z+=(t-(t%16))*f1[y][j];
 83             }
 84             
 85             //g[y]=f[x]+g[x]-(f[y]+tot[y]*a[i].d)
 86             g0[y]+=f0[x]+g0[x]-z;
 87             for(int j=0;j<=15;j++) g1[y][j]+=f1[x][j]+g1[x][j]-c[j];
 88             
 89             //g[y]+=(n-tot[y])*a[i].d
 90             for(int j=0;j<=15;j++) c[j]=g1[y][j];
 91             for(int j=0;j<=15;j++) 
 92             {
 93                 int t=j+now;
 94                 g1[y][t%16]=c[j];
 95                 g0[y]+=(t-(t%16))*c[j];
 96             }
 97             dfs2(y,x);
 98         }
 99     }
100 }
101 
102 int main()
103 {
104     // freopen("a.in","r",stdin);
105     freopen("warehouse.in","r",stdin);
106     freopen("warehouse.out","w",stdout);
107     len=0;
108     memset(first,0,sizeof(first));
109     scanf("%d%d",&n,&m);
110     for(int i=1;i<n;i++)
111     {
112         int x,y,d;
113         scanf("%d%d%d",&x,&y,&d);
114         ins(x,y,d),ins(y,x,d);
115     }
116     memset(f0,0,sizeof(f0));
117     memset(f1,0,sizeof(f1));
118     memset(g0,0,sizeof(g0));
119     memset(g1,0,sizeof(g1));
120     dfs1(1,0);dfs2(1,0);
121     int ans=0;
122     for(int i=1;i<=n;i++) 
123     {
124         ans=f0[i]+g0[i];
125         for(int j=0;j<=15;j++)
126         {
127             int now=j^m;
128             ans+=(f1[i][j]+g1[i][j])*now;
129         }
130         ans-=m;
131         printf("%d
",ans);
132     }
133     return 0;
134 }
原文地址:https://www.cnblogs.com/KonjakJuruo/p/5774339.html