BZOJ 1782 洛谷 2982 [Usaco2010 Feb]slowdown 慢慢游

【题解】

  一头牛走到i,相当于把i点的子树的点权都加1,查询减慢的次数就是查询目的地的点权。

  预处理dfs序,某个点的子树的dfs序是连续的一段。差分后用树状数组维护,变成点修区查。或者直接线段树区修点查。

  

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define N 200010
 4 #define rg register
 5 using namespace std;
 6 int n,tot,dfn[N],size[N],p[N],t[N],last[N];
 7 struct edge{
 8     int to,pre;
 9 }e[N];
10 inline int read(){
11     int k=0,f=1; char c=getchar();
12     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
13     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
14     return k*f;
15 }
16 inline void add(int x,int y){for(;x<=n;x+=x&-x) t[x]+=y;}
17 inline int query(int x){
18     int ret=0; for(;x;x-=x&-x) ret+=t[x]; return ret;
19 }
20 void dfs(int x){
21     dfn[x]=++tot; size[x]=1;
22     for(rg int i=last[x],to;i;i=e[i].pre)
23         if(!dfn[to=e[i].to]) dfs(to),size[x]+=size[to];
24 }
25 int main(){
26     n=read();
27     for(rg int i=1;i<n;i++){
28         int u=read(),v=read();
29         e[++tot]=(edge){v,last[u]}; last[u]=tot;
30         e[++tot]=(edge){u,last[v]}; last[v]=tot;
31     }
32     tot=0; dfs(1);
33     for(rg int i=1;i<=n;i++){
34         int x=read();
35         printf("%d\n",query(dfn[x]));
36         add(dfn[x],1); add(dfn[x]+size[x],-1);
37     }
38     return 0;
39 }
View Code

 

posted @ 2018-04-12 08:26  Driver_Lao  阅读(203)  评论(0编辑  收藏  举报