hdu某道题

题目大意:给出一棵树,求以i为根节点的子树中有多少个节点标号比i小
得到dfs序之后,用树状数组求第i个数之前比第i个数小的数的个数
ans[i]=ed[i]-st[i];

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
#define MAXN 100010
int l,tot,n,p,x,y;
struct point{
 int y;
 int next;
}edge[MAXN*2];
typedef int arr[MAXN*4];
arr st,ed,c,head,ans;




void add(int x,int y)
{
    l++;
    edge[l].y=y;
    edge[l].next=head[x];
    head[x]=l;
}
void dfs(int x)
{

    tot++;
    st[x]=tot;
    int p=head[x];//一定要定义成局部变量
    while (p)
    {
        if (st[edge[p].y]==0)
        {
            dfs(edge[p].y);
            tot++;
        }
        p=edge[p].next;
    }
    if (st[x]==tot) tot++;
    ed[x]=tot;
}



int lowbit(int x)
{
    return (x & (-x));
}
void updata(int x,int y)
{
    while (x<=tot)
    {
        c[x]+=y;
        x+=lowbit(x);
    }
}
int sum(int x)
{
    int tmp=0;
    while (x)
    {
        tmp+=c[x];
        x-=lowbit(x);
    }
    return tmp;
}







int main()
{
    cin>>n>>p;
    while (n!=0 && p!=0)
    {
        l=0;
        memset(head,0,sizeof(head));
        for (int i = 1;i < n;i++)
        {
            cin>>x>>y;
            add(x,y);
            add(y,x);
        }
        tot=0;
        memset(st,0,sizeof(st));
        memset(ed,0,sizeof(ed));
        dfs(p);



        memset(c,0,sizeof(c));
        for (int i = 1;i <= n;i++)
        {
            ans[i]=sum(ed[i])-sum(st[i]);
            updata(st[i],1);//只记开始的即可
        }
        for (int i = 1;i <= n;i++)
            cout<<ans[i]<<' ';
        cout<<endl;
        cin>>n>>p;
    }
    return 0;
}

非递归:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;

#define MAXN 100010

int l,tot,n,p,x,y;
struct point{
 int y;
 int next;
}edge[MAXN*2];
typedef int arr[MAXN*4];
arr st,ed,c,head,ans,sta;
bool vis[100010];

void add(int x,int y)
{
    l++;
    edge[l].y=y;
    edge[l].next=head[x];
    head[x]=l;
}
void dfs(int x)
{
    int now=1;
    int tmp;
    vis[x]=1;
    sta[now]=x;
    while (now)
    {
        tmp=sta[now];
        tot++;
        if (st[tmp]==0) st[tmp]=tot;
        int flag=0;
        p=head[tmp];
        while (p)
        {
            if (vis[edge[p].y]==0)
            {
                now++;
                vis[edge[p].y]=1;
                sta[now]=edge[p].y;
                flag=1;
                break;//!!
            }
            p=edge[p].next;
        }
        if (flag==0)
        {
            if (st[tmp]==tot) tot++;
            ed[tmp]=tot;
            now--;
        }
    }
}


int lowbit(int x)
{
    return (x & (-x));
}
void updata(int x,int y)
{
    while (x<=tot)
    {
        c[x]+=y;
        x+=lowbit(x);
    }
}
int sum(int x)
{
    int tmp=0;
    while (x)
    {
        tmp+=c[x];
        x-=lowbit(x);
    }
    return tmp;
}
int main()
{
    cin>>n>>p;
    while (n!=0 && p!=0)
    {
        l=0;
        memset(head,0,sizeof(head));
        for (int i = 1;i < n;i++)
        {
            cin>>x>>y;
            add(x,y);
            add(y,x);
        }
        tot=0;
        memset(st,0,sizeof(st));
        memset(ed,0,sizeof(ed));
        memset(vis,0,sizeof(vis));
        dfs(p);
        memset(c,0,sizeof(c));
        for (int i = 1;i <= n;i++)
        {
            ans[i]=sum(ed[i])-sum(st[i]);
            updata(st[i],1);//只记开始的即可
        }
        for (int i = 1;i < n;i++)
            cout<<ans[i]<<' ';
        cout<<ans[n]<<endl;
        cin>>n>>p;
    }
    return 0;
}

你可能感兴趣的:(C++,DFS,树状数组)