zoukankan      html  css  js  c++  java
  • [Hdu3887]Counting Offspring

    [Hdu3887]Counting Offspring
    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.
    Input

    Multiple 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.
    给你一个树,问你对于每个节点,它的子树上标号比它小的点有多少个
    N<=100000
    Output

    For 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

    Sol:跑出dfs序来,然后树状数组查询下就好了。此题还可以用线段树的合并来做。

    参考:https://www.cnblogs.com/cutemush/p/11835761.html

    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 100000+10;
    vector<int>G[maxn];
    int n,p,t;
    int l[maxn],r[maxn],tree[maxn];
    void dfs(int u,int fa)
    //求出dfs序,某个树上所有结点必然是连在一起的 
    {
        l[u]  = ++t; 
        int len = G[u].size();
        for(int i=0;i<len;i++)
        {
            int v = G[u][i];
            if(v==fa) continue;
            dfs(v,u);
        }
        r[u] = t; 
    	
    }
    inline int lowbit(int i)
    {
    	return i&(-i); 
    }
    inline void add(int i,int d)
    {
        while(i<=n)
        {
            tree[i] += d;
            i += lowbit(i);
        }
    }
    inline int getsum(int i)
    {
        int ans = 0;
        while(i)
        {
            ans += tree[i];
            i -= lowbit(i);
        }
        return ans;
    }
    int main()
    {
        int u,v;
        while(scanf("%d%d",&n,&p))//N个点,P为root点 
        {
            if(n==0&&p==0) break;
            memset(tree,0,sizeof(tree));
            for(int i=0;i<=n;i++) 
    		    G[i].clear();
            for(int i=1;i<n;i++)
    		{
                scanf("%d%d",&u,&v);
                G[u].push_back(v);
                G[v].push_back(u);
            }
            t = 0; 
           dfs(p,-1);
          // for (int i=1;i<=n;i++)
           //cout<<i<<"  "<<l[i]<<"  "<<r[i]<<endl;
            for(int i=1;i<=n;i++)
    		//统计对于i来说,有多少个点值比它小 
            {
                printf("%d",getsum(r[i])-getsum(l[i]-1));  
                //统计从[l(i),r(i)]这一段中有多少数字比i小 
                if(i==n) 
    			   printf("
    ");
                else 
    			    printf(" ");
                add(l[i],1);
            }
        }
        return 0;
    }
    /*
    input 
    4 4
    4 3
    4 2
    3 1
    结点编号 入   出 
    1        3    3
    2        4    4
    3        2    3
    4        1    4
    output
    0 0 1 3
    */
    
     
    

      

  • 相关阅读:
    英语cabardine麝香cabardine单词
    英语dialogite红纹石dialogite菱锰矿
    英语chiltonite葡萄石chiltonite单词
    英语chrysopal金绿宝石chrysopal单词
    Android系统默认对话框添加图片
    入门rocketmq从浅到深
    通用mapper认识和用法
    java开发注解大全
    solr的认识、linux下安装、java下使用(含下载资源)
    RSA签名和验签Util
  • 原文地址:https://www.cnblogs.com/cutemush/p/11794548.html
Copyright © 2011-2022 走看看