dfs序 + 树状数组
You are given a tree, it’s root is p, and the node is numbered from 1 to n. Now define f(i) as the number of nodes whose number is less than i in all the succeeding nodes of node i. Now we need to calculate f(i) for any possible i.
InputMultiple cases (no more than 10), for each case:
The first line contains two integers n (0<n<=10^5) and p, representing this tree has n nodes, its root is p.
Following n-1 lines, each line has two integers, representing an edge in this tree.
The input terminates with two zeros.OutputFor each test case, output n integer in one line representing f(1), f(2) … f(n), separated by a space.Sample Input
15 7 7 10 7 1 7 9 7 3 7 4 10 14 14 2 14 13 9 11 9 6 6 5 6 8 3 15 3 12 0 0Sample Output
0 0 0 0 0 1 6 0 3 1 0 0 0 2 0
题意 : 给你一颗带根的树,询问每个结点他的孩子中比他小的点的个数
思路分析: 对于一颗树我们可以找到他的 dfs序,将其变成一维的数组的结构,在寻找的同时再添加一个时间戳,然后树状数组维护下标就可以,当然主席树也可以
代码示例 :
#define ll long long const int maxn = 1e5+5; const int mod = 1e9+7; const double eps = 1e-9; const double pi = acos(-1.0); const int inf = 0x3f3f3f3f; int n, p; vector<int>ve[maxn]; int s[maxn], e[maxn]; int cnt = 0; void dfs(int x, int fa){ s[x] = ++cnt; for(int i = 0; i < ve[x].size(); i++){ int to = ve[x][i]; if (to == fa) continue; dfs(to, x); } e[x] = cnt; } int ans[maxn]; int c[maxn]; int lowbit(int x){return x&(-x);} void add(int x){ int sum = 0; for(int i = x; i <= n; i += lowbit(i)){ c[i]++; } } int query(int x){ int sum = 0; for(int i = x; i >= 1; i -= lowbit(i)){ sum += c[i]; } return sum; } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); int a, b; while(scanf("%d%d", &n, &p) && n+p){ for(int i = 1; i <= n; i++) ve[i].clear(); cnt = 0; for(int i = 1; i < n; i++){ scanf("%d%d", &a, &b); ve[a].push_back(b); ve[b].push_back(a); } dfs(p, 0); memset(c, 0, sizeof(c)); for(int i = 1; i <= n; i++){ int st = s[i]; int et = e[i]; ans[i] = query(et)-query(st-1); add(st); } for(int i = 1; i <= n; i++){ printf("%d%c", ans[i], i==n?'\n':' '); } } return 0; }
东北日出西边雨 道是无情却有情