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 0
Sample 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?'
':' ');
        }
    }
    return 0;
}
东北日出西边雨 道是无情却有情
原文地址:https://www.cnblogs.com/ccut-ry/p/8847885.html