树上差分模板题吧。唯一需要注意的也是值得讲的就是:边化点。
对于(i,j)连接的边,我们记录这条边的方式就是把(i,j)中深度大的点的id作为这条边的编号,第二遍dfs统计的时候可以直接记下来。
提一下树上差分:
边上操作:++s[u],++s[v],s[lca(u,v)]-=2;
点上操作:++s[u],++s[v],--s[lca(u,v)],--s[fa[lca(u,v)]];
1 #include<cstdio> 2 #define it register int 3 #define il inline 4 const int N=500005; 5 int u,v,h[N],nxt[N],adj[N],t,n,fa[N][20],d[N],lc,uu[N],vv[N],s[N],id[N],m,ans[N]; 6 il void add(){ 7 nxt[++t]=h[u],h[u]=t,adj[t]=v,nxt[++t]=h[v],h[v]=t,adj[t]=u; 8 } 9 il void dfs(it x){ 10 d[x]=d[fa[x][0]]+1; 11 for(it i=h[x];i;i=nxt[i]) 12 if(adj[i]!=fa[x][0]) 13 fa[adj[i]][0]=x,dfs(adj[i]); 14 } 15 il void DFS(it x){ 16 for(it i=h[x];i;i=nxt[i]) 17 if(adj[i]!=fa[x][0]) 18 DFS(adj[i]),s[x]+=s[adj[i]]; 19 ans[id[x]]=s[x]; 20 } 21 il void sp(int &p,int &q){ 22 p+=q,q=p-q,p-=q; 23 } 24 il void lca(it p,it q){ 25 if(d[p]<d[q]) sp(p,q); 26 it ds=d[p]-d[q]; 27 for(it i=17;i>=0;--i) 28 if(ds&(1<<i)) p=fa[p][i]; 29 if(p==q){lc=p;return;} 30 for(it i=17;i>=0;--i) 31 if(fa[p][i]!=fa[q][i]) 32 p=fa[p][i],q=fa[q][i]; 33 lc=fa[p][0]; 34 } 35 il void fr(int &num){ 36 num=0;char c=getchar();int p=1; 37 while(c<'0'||c>'9') c=='-'?p=-1,c=getchar():c=getchar(); 38 while(c>='0'&&c<='9') num=num*10+c-'0',c=getchar(); 39 num*=p; 40 } 41 int main(){ 42 fr(n); 43 for(it i=1;i<n;++i) fr(u),fr(v),add(),uu[i]=u,vv[i]=v; 44 dfs(1); 45 for(it i=1;i<n;++i) d[uu[i]]>d[vv[i]]?id[uu[i]]=i:id[vv[i]]=i; 46 fr(m); 47 for(it j=1;j<=17;++j) 48 for(it i=1;i<=n;++i) 49 fa[i][j]=fa[fa[i][j-1]][j-1]; 50 while(m--) 51 fr(u),fr(v),++s[u],++s[v],lca(u,v),s[lc]-=2; 52 DFS(1); 53 for(it i=1;i<n;++i) printf("%d ",ans[i]); 54 return 0; 55 }