hdu3887(dfs序)

来源:互联网 发布:蓝鸥学校java培训 编辑:程序博客网 时间:2024/05/18 19:45
问你对于每个节点,它的子树上标号比它小的点有多少个

子树的问题,dfs序可以很轻松的解决,因为点在它的子树上,所以在线段树中,必定在它的两个时间戳的区间之间,所以我们只需要从小到大考虑,它的区间里有多少个点已经放了,然后再把它放进去。很容易的解决了

#include<cstdio>#include<vector>#include<cstring>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){    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))    {        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++)        {            printf("%d",getsum(r[i])-getsum(l[i]-1));            if(i==n) printf("\n");            else printf(" ");            add(l[i],1);        }    }    return 0;}