noip的难题,lca+dfs统计
思路其实不难,但是要代码实现0 0,有点烦(还是我太菜了!)。
调了好久,wa了好几发555.
#include<bits/stdc++.h> using namespace std; const int maxn=600010,N=600010; int rs[maxn],rt[maxn],cnt=0,head[maxn],dep[maxn],f[maxn][20],dis[maxn],bucket[maxn*2],root=1,w[maxn],spn[maxn],ans[maxn]; bool visit[maxn]; struct edge{ int to,next; }e[maxn]; vector<int>v1[maxn],v2[maxn],v3[maxn]; //v1[i]以i为lca的起点,v2[i]以i为终的起点,v3[i]以i为lca的终点 int lca(int a,int b){ if(dep[a]<dep[b])swap(a,b); for(int i=0;i<20;++i) if(((dep[a]-dep[b])>>i)&1)a=f[a][i]; if(a==b)return a; for(int i=19;i>=0;--i){ if(f[a][i]!=f[b][i]){ a=f[a][i];b=f[b][i]; } } return f[a][0]; } void add_edge(int s,int t){ e[++cnt].next=head[s];e[cnt].to=t;head[s]=cnt; e[++cnt].next=head[t];e[cnt].to=s;head[t]=cnt; } int get_dis(int a,int b){ return dis[a]+dis[b]-2*dis[lca(a,b)]; } void dfs(int u){ for(int i=head[u];i;i=e[i].next){ if(!dep[e[i].to]){ dis[e[i].to]=dis[u]+1; f[e[i].to][0]=u; dep[e[i].to]=dep[u]+1; dfs(e[i].to); } } } void dfs1(int u){ visit[u]=1; int pre=bucket[w[u]+dep[u]+N]; for(int i=head[u];i;i=e[i].next){ if(!visit[e[i].to]){ dfs1(e[i].to); } } bucket[N+dep[u]]+=spn[u]; ans[u]+=bucket[w[u]+dep[u]+N]-pre; int len=v1[u].size(); for(int i=0;i<len;++i){ bucket[dep[v1[u][i]]+N]--; } } void dfs2(int u){ visit[u]=1; int pre=bucket[w[u]-dep[u]+N]; for(int i=head[u];i;i=e[i].next){ if(!visit[e[i].to]){ dfs2(e[i].to); } } for(int i=0;i<v2[u].size();++i){ bucket[v2[u][i]+N]++; } ans[u]+=bucket[w[u]-dep[u]+N]-pre; for(int i=0;i<v3[u].size();++i){ bucket[v3[u][i]+N]--; } } int main(){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n-1;++i){ int s,t; scanf("%d%d",&s,&t); add_edge(s,t); } dep[root]=1; dfs(root); for(int j=0;j<20;++j){ for(int i=1;i<=n;++i){ if(f[i][j-1])f[i][j]=f[f[i][j-1]][j-1]; } } for(int i=1;i<=n;++i)scanf("%d",&w[i]); for(int i=1;i<=m;++i){ scanf("%d%d",&rs[i],&rt[i]); int l=lca(rs[i],rt[i]); spn[rs[i]]++; v1[l].push_back(rs[i]); v2[rt[i]].push_back(get_dis(rs[i],rt[i])-dep[rt[i]]); v3[l].push_back(get_dis(rs[i],rt[i])-dep[rt[i]]); } memset(visit,0,sizeof(visit)); dfs1(root); memset(visit,0,sizeof(visit)); dfs2(root); for(int i=1;i<=m;++i){ int l=lca(rs[i],rt[i]); if(dep[rs[i]]==dep[l]+w[l])ans[l]--; } for(int i=1;i<=n;++i)printf("%d ",ans[i]); return 0; }