BZOJ_1782
刚看完一部惊悚片,赶紧A个题缓和一下气氛,要不该做噩梦了……
这个题目相当于每个节点都有一个标号,然后求从根到当前节点的路径上,小于当前节点的标号一共有多少个,可以在dfs的时候用树状数组来统计。
#include<stdio.h> #include<string.h> #define MAXD 100010 #define MAXM 200010 int N, D, first[MAXD], e, next[MAXM], v[MAXM], sum[MAXD], who[MAXD], res[MAXD]; void update(int x, int d) { for(; x <= N; x += x & -x) sum[x] += d; } int query(int x) { int ans = 0; for(; x > 0; x -= x & -x) ans += sum[x]; return ans; } void add(int x, int y) { v[e] = y; next[e] = first[x], first[x] = e ++; } void init() { memset(first, -1, sizeof(first[0]) * (N + 1)), e = 0; for(int i = 1; i < N; i ++) { int x, y; scanf("%d%d", &x, &y); add(x, y), add(y, x); } for(int i = 1; i <= N; i ++) { int p; scanf("%d", &p); who[p] = i; } } void dfs(int cur, int fa) { res[who[cur]] = query(who[cur]); update(who[cur], 1); for(int i = first[cur]; i != -1; i = next[i]) if(v[i] != fa) dfs(v[i], cur); update(who[cur], -1); } void solve() { memset(sum, 0, sizeof(sum[0]) * (N + 1)); dfs(1, -1); for(int i = 1; i <= N; i ++) printf("%d\n", res[i]); } int main() { while(scanf("%d", &N) == 1) { init(); solve(); } return 0; }