HDU 3887:Counting Offspring(DFS序+树状数组)
http://acm.hdu.edu.cn/showproblem.php?pid=3887
题意:给出一个有根树,问对于每一个节点它的子树中有多少个节点的值是小于它的。
思路:这题和那道苹果树是一样的,DFS序+树状数组,一开始没想到,用了DFS序+排序,结果超时了。在in和out之间的时间戳是该节点子树的范围,从后往前扫,再删掉大的,这样可以满足值小于该节点的条件。
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <string> 7 #include <iostream> 8 #include <stack> 9 #include <map> 10 #include <queue> 11 using namespace std; 12 #define N 100010 13 #define INF 0x3f3f3f3f 14 struct node 15 { 16 int v, nxt; 17 }edge[N*2]; 18 int bit[N*2], n, tot, head[N], tim, in[N], out[N], ans[N]; 19 20 void add(int u, int v) 21 { 22 edge[tot].v = v; edge[tot].nxt = head[u]; head[u] = tot++; 23 } 24 25 void dfs(int u, int fa) 26 { 27 in[u] = ++tim; 28 for(int i = head[u]; ~i; i = edge[i].nxt) { 29 int v = edge[i].v; 30 if(v == fa) continue; 31 dfs(v, u); 32 } 33 out[u] = tim; 34 } 35 36 int lowbit(int x) 37 { 38 return x & (-x); 39 } 40 41 void update(int x, int val) 42 { 43 while(x <= tim) { 44 bit[x] += val; 45 x += lowbit(x); 46 } 47 } 48 49 int query(int x) 50 { 51 int ans = 0; 52 while(x) { 53 ans += bit[x]; 54 x -= lowbit(x); 55 } 56 return ans; 57 } 58 59 int main() 60 { 61 int rt; 62 while(scanf("%d%d", &n, &rt), n + rt) { 63 memset(head, -1, sizeof(head)); 64 memset(bit, 0, sizeof(bit)); 65 tot = tim = 0; 66 for(int i = 1; i < n; i++) { 67 int u, v; 68 scanf("%d%d", &u, &v); 69 add(u, v); add(v, u); 70 } 71 dfs(rt, -1); 72 for(int i = 1; i <= n; i++) update(i, 1); 73 for(int i = n; i >= 1; i--) { 74 ans[i] = query(out[i]) - query(in[i]); 75 update(in[i], -1); 76 } 77 for(int i = 1; i <= n; i++) { 78 if(i == n) printf("%d\n", ans[i]); 79 else printf("%d ", ans[i]); 80 } 81 } 82 return 0; 83 }