zoukankan      html  css  js  c++  java
  • 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;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    linux下tomcat内存溢出
    leetcode
    HDU 4810 Wall Painting (位操作-异或)
    详解Java中的访问控制修饰符(public, protected, default, private)
    mpvue开发微信小程序之时间+日期选择器
    多行文本溢出隐藏
    swift 多态函数方式
    swift 多态函数方式
    swift 多态函数方式
    swift 多态函数方式
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/8847885.html
Copyright © 2011-2022 走看看