1. 程式人生 > >【LCA+樹上差分】天天愛跑步

【LCA+樹上差分】天天愛跑步

blog 分支 div fin out 答案 簡單 printf 但是

困擾我半年多的題終於做出來了

一開始我的做法是想在回溯的時候統計答案,但是各個分支之間又會相互影響,然後就不會做了

看完別人的題解後發現用桶的前後狀態做差來統計答案更簡單

 1 #include <cstdio>
 2 #include <vector>
 3 #include <iostream>
 4 #define db(x) cout<<#x<<"="<<x<<endl; 
 5 using namespace std;
 6 const int N=300010;
 7 typedef pair<int
,int> P; 8 struct E{ 9 int next,to; 10 }e[2*N]; 11 int n,m,a,b,sz=0,head[N],w[N],dep[N],fa[N][20],chk1[3*N],chk2[3*N],ans[N]; 12 vector<int> p1[N],p2[N],q1[N],q2[N]; 13 void insert(int a,int b) 14 { 15 sz++; 16 e[sz].next=head[a]; 17 head[a]=sz; 18 e[sz].to=b; 19 } 20 void
dfs(int x,int f) 21 { 22 for (int i=1;i<=19;i++) fa[x][i]=fa[fa[x][i-1]][i-1]; 23 for (int i=head[x];i;i=e[i].next) 24 if (e[i].to!=f) 25 { 26 dep[e[i].to]=dep[x]+1; 27 fa[e[i].to][0]=x; 28 dfs(e[i].to,x); 29 } 30 } 31 int lca(int
a,int b) 32 { 33 if (dep[a]<dep[b]) swap(a,b); 34 int t=dep[a]-dep[b]; 35 for (int i=19;i>=0;i--) 36 if (t&(1<<i)) a=fa[a][i]; 37 for (int i=19;i>=0;i--) 38 if (fa[a][i]!=fa[b][i]) a=fa[a][i],b=fa[b][i]; 39 if (a==b) return a; 40 return fa[a][0]; 41 } 42 int solve(int x,int f) 43 { 44 int s=chk1[N+dep[x]+w[x]]+chk2[N+dep[x]-w[x]]; 45 for (int i=0;i<p1[x].size();i++) chk1[N+p1[x][i]]++; 46 for (int i=0;i<p2[x].size();i++) chk2[N+p2[x][i]]++; 47 for (int i=head[x];i;i=e[i].next) 48 if (e[i].to!=f) solve(e[i].to,x); 49 ans[x]+=chk1[N+dep[x]+w[x]]+chk2[N+dep[x]-w[x]]-s; 50 for (int i=0;i<q1[x].size();i++) chk1[N+q1[x][i]]--; 51 for (int i=0;i<q2[x].size();i++) chk2[N+q2[x][i]]--; 52 } 53 int main() 54 { 55 scanf("%d%d",&n,&m); 56 for (int i=1;i<n;i++) 57 { 58 scanf("%d%d",&a,&b); 59 insert(a,b);insert(b,a); 60 } 61 dfs(1,1); 62 for (int i=1;i<=n;i++) scanf("%d",&w[i]); 63 for (int i=1;i<=m;i++) 64 { 65 scanf("%d%d",&a,&b); 66 int s=lca(a,b); 67 if (w[s]==dep[a]-dep[s]) ans[s]--; 68 p1[a].push_back(dep[a]); 69 p2[b].push_back(-(dep[a]-2*dep[s])); 70 q1[s].push_back(dep[a]); 71 q2[s].push_back(-(dep[a]-2*dep[s])); 72 } 73 solve(1,1); 74 for (int i=1;i<=n;i++) printf("%d ",ans[i]); 75 }

【LCA+樹上差分】天天愛跑步