luogu P2982 [USACO10FEB]Slowing down G
题面传送门
很裸的一道题。感觉难度虚高。
可以先把这棵树的欧拉序跑出来,然后每次询问是根节点到当前点的权值,那么树状数组随便维护一下就好了。
代码实现:
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,k,x,y,ans,tot,pus,dfn[200039],l[100039],r[100039],dh,f[200039];
struct yyy{int to,z;};
struct ljb{
int head,h[100039];
yyy f[200039];
inline void add(int x,int y){
f[++head]=(yyy){y,h[x]};
h[x]=head;
}
}s;
inline void dfs(int x,int last){
dfn[++dh]=x;
l[x]=dh;
int cur=s.h[x];
yyy tmp;
while(cur!=-1){
tmp=s.f[cur];
if(tmp.to!=last) dfs(tmp.to,x);
cur=tmp.z;
}
dfn[++dh]=x;
r[x]=dh;
}
inline void get(int x,int y){while(x<=2*n) f[x]+=y,x+=x&-x;}
inline int find(int x){int ans=0;while(x) ans+=f[x],x-=x&-x;return ans;}
int main(){
register int i;
memset(s.h,-1,sizeof(s.h));
scanf("%d",&n);
for(i=1;i<n;i++) scanf("%d%d",&x,&y),s.add(x,y),s.add(y,x);
dfs(1,0);
for(i=1;i<=n;i++){
scanf("%d",&x);
printf("%d\n",find(l[x]));
get(l[x],1);
get(r[x],-1);
}
}