【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 }
NOIP2016 D1 T2

 

posted @ 2017-08-30 21:17  Child-Single  阅读(760)  评论(0编辑  收藏  举报