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 }