hdu某道题

来源:互联网 发布:微信公众号开发 php 编辑:程序博客网 时间:2024/05/16 08:30

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

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>using namespace std;#define MAXN 100010int 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 100010int 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;}
0 0