聯賽模擬測試9 C. 小奇的倉庫(warehouse)
阿新 • • 發佈:2020-10-05
題目描述
分析
\(m=0\) 是顯然的換根 \(dp\)
當 \(m\) 不為\(0\),沿用換根\(dp\)思路
m的範圍很小,加上異或是位運算
先任選一個根,\(dfs\)求出 到每個點的距離之和 和 距離最後四位為\(0 \sim 15\)的方案數
與\(m=0\)時差不多,隨便搞一下就能寫出換根的變化量
程式碼
#include<cstdio> #include<cstring> inline int read(){ int x=0,fh=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') fh=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*fh; } const int maxm=1e6+5,maxn=1e5+5; int head[maxm],tot=1; struct asd{ int to,next,val; }b[maxm]; void ad(int aa,int bb,int cc){ b[tot].to=bb; b[tot].next=head[aa]; b[tot].val=cc; head[aa]=tot++; } int n,m,f[maxn],g[maxn],fcnt[maxn][16],gcnt[maxn][16],siz[maxn],zy[50]; void debug(int now){ printf("begin-----debug\n"); printf("--------------------\n"); printf("g陣列 節點編號 %d\n",now); for(int i=0;i<=15;i++){ if(gcnt[now][i])printf("長度:%d 數量:%d\n",i,gcnt[now][i]); } printf(">16的長度 %d\n",g[now]); printf("f陣列 節點編號 %d\n",now); for(int i=0;i<=15;i++){ if(fcnt[now][i])printf("長度:%d 數量:%d\n",i,fcnt[now][i]); } printf(">16的長度 %d\n",f[now]); printf("end-----debug\n\n\n"); } #define findbug printf("當前節點:%d 父親節點:%d 兒子節點:%d\n",now,fa,u) void dfs(int now,int fa){ siz[now]=1; for(int i=head[now];i!=-1;i=b[i].next){ int u=b[i].to; if(u==fa) continue; dfs(u,now); int cs=b[i].val; cs=(cs>>4); cs=(cs<<4); g[now]+=g[u]+cs*siz[u]; cs=(b[i].val&15); for(int j=0;j<=30;j++){ zy[j]=0; } for(int j=0;j<=15;j++){ int nval=j+cs; zy[nval]+=gcnt[u][j]; } zy[cs]++; for(int j=0;j<=30;j++){ if(j<=15){ gcnt[now][j]+=zy[j]; } else { gcnt[now][j-16]+=zy[j]; g[now]+=zy[j]*16; } } siz[now]+=siz[u]; } } void dfs2(int now,int fa){ if(now==1){ f[now]=g[now]; for(int i=0;i<=15;i++){ fcnt[now][i]=gcnt[now][i]; } } for(int i=head[now];i!=-1;i=b[i].next){ int u=b[i].to; if(u==fa) continue; int cs=b[i].val; cs=(cs>>4); cs=(cs<<4); f[u]=f[now]-g[u]-siz[u]*cs; f[u]+=(n-siz[u])*cs; cs=(b[i].val&15); for(int j=0;j<=30;j++){ zy[j]=0; } for(int j=0;j<=15;j++){ int nval=j+cs; zy[nval]+=gcnt[u][j]; } for(int j=0;j<=30;j++){ if(j<=15){ fcnt[u][j]=fcnt[now][j]-zy[j]; } else { fcnt[u][j-16]-=zy[j]; f[u]-=zy[j]*16; } } fcnt[u][cs]--; for(int j=0;j<=30;j++){ zy[j]=0; } for(int j=0;j<=15;j++){ int nval=j+cs; zy[nval]+=fcnt[u][j]; } zy[cs]++; for(int j=0;j<=30;j++){ if(j<=15){ fcnt[u][j]=gcnt[u][j]+zy[j]; } else { fcnt[u][j-16]+=zy[j]; f[u]+=zy[j]*16; } } f[u]+=g[u]; dfs2(u,now); } } int main(){ freopen("warehouse.in","r",stdin); freopen("warehouse.out","w",stdout); memset(head,-1,sizeof(head)); n=read(),m=read(); int aa,bb,cc; for(int i=1;i<n;i++){ aa=read(),bb=read(),cc=read(); ad(aa,bb,cc); ad(bb,aa,cc); } dfs(1,0); dfs2(1,0); for(int i=1;i<=n;i++){ int nans=0; for(int j=0;j<=15;j++){ nans=(nans+(j^m)*fcnt[i][j]); } printf("%d\n",f[i]+nans); } return 0; }