【NOIP2016】天天爱跑步——LCA+树上差分
真是一道神题(大家普遍认为是去年NOIP最难的一道so......),然而之前并没有写过关于树上差分的题目,所以自己想了一晚上+一早上都没能想出来(搞的心神不宁T^T)->还是太弱
题解感觉没什么必要发了,网上的都差不多吧(都是nlogn的写法),需要的话可以看一下yy dalao的题解,还是蛮详细的-->戳这里
听说能优化成O(n)的,有时间的话学一下吧感觉好神啊。
//写完调了好久发现没建反向边/////捂脸
//最近效率好低啊QAQ,NOIP要来了啊啊啊啊,刷题刷题~
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<algorithm> 5 const int maxn=3e5+5; 6 using namespace std; 7 /*---------------------------------------------------------*/ 8 int n,m,tot=0; 9 struct node{ 10 int next,to; 11 }e[maxn*2]; 12 struct pos{int x,s;}; 13 int first[maxn],fa[maxn][22],w[maxn],deep[maxn],an[maxn],ans1[maxn],ans2[maxn<<1]; 14 bool ok[maxn]; 15 vector<pos>e1[maxn],e2[maxn<<1]; 16 int read() 17 { 18 int ans=0,f=1;char c=getchar(); 19 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 20 while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();} 21 return ans*f; 22 } 23 /*------------------------------------------------------------*/ 24 void add(int x,int y) 25 { 26 tot++;e[tot].next=first[x];first[x]=tot;e[tot].to=y; 27 } 28 void dfs1(int x) 29 { 30 ok[x]=1; 31 for(int i=1;(1<<i)<=deep[x];i++) 32 fa[x][i]=fa[fa[x][i-1]][i-1]; 33 for(int i=first[x];i;i=e[i].next){ 34 int to=e[i].to; 35 if(ok[to])continue; 36 deep[to]=deep[x]+1; 37 fa[to][0]=x; 38 dfs1(to); 39 } 40 } 41 int lca(int x,int y) 42 { 43 if(deep[x]>deep[y])swap(x,y); 44 int d=deep[y]-deep[x]; 45 for(int i=0;(1<<i)<=d;i++) 46 if((1<<i)&d)y=fa[y][i]; 47 if(x==y)return x; 48 for(int i=20;i>=0;i--){ 49 if((1<<i)>deep[x]||(1<<i)>deep[y]||fa[x][i]==fa[y][i])continue; 50 x=fa[x][i];y=fa[y][i]; 51 } 52 return fa[x][0]; 53 } 54 void dfs2(int x) 55 { 56 an[x]-=ans1[deep[x]+w[x]]; 57 an[x]-=ans2[w[x]-deep[x]+n]; 58 for(int i=0;i<e1[x].size();i++)ans1[e1[x][i].x]+=e1[x][i].s; 59 for(int i=0;i<e2[x].size();i++)ans2[e2[x][i].x+n]+=e2[x][i].s; 60 for(int i=first[x];i;i=e[i].next){ 61 int to=e[i].to; 62 if(to==fa[x][0])continue; 63 dfs2(to); 64 } 65 an[x]+=ans1[w[x]+deep[x]]+ans2[w[x]-deep[x]+n]; 66 } 67 int main() 68 { 69 int u,v,si,ti; 70 n=read();m=read(); 71 for(int i=1;i<=n-1;i++){ 72 u=read();v=read(); 73 add(u,v);add(v,u); 74 } 75 for(int i=1;i<=n;i++)w[i]=read(); 76 deep[1]=1; 77 dfs1(1); 78 for(int i=1;i<=m;i++){ 79 si=read();ti=read(); 80 int gr=lca(si,ti); 81 e1[si].push_back((pos){deep[si],1}); 82 e1[gr].push_back((pos){deep[si],-1}); 83 e2[ti].push_back((pos){deep[si]-(deep[gr]<<1),1}); 84 e2[fa[gr][0]].push_back((pos){deep[si]-(deep[gr]<<1),-1}); 85 } 86 dfs2(1); 87 for(int i=1;i<=n-1;i++) 88 printf("%d ",an[i]); 89 printf("%d",an[n]); 90 return 0; 91 }