HDOJ3887-DFS人工栈,树状数组

8 篇文章 0 订阅
/* 
树状数组。dfs过程中,进入一个节点x前求一次sum(x-1),然后add操作,递归返回节点x后再求一次sum(x-1) 
      两次sum操作的差值就是比x小的个数 
      本题数据量大,递归太深可能爆栈,一般用while+人工栈模拟递归的过程,当然c++可以设置栈的大小,这样就不会爆栈了
我不告诉你思路是看来的~~可取的是人工栈过了一遍。
*/  
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;

const int NN=100010;

vector<int> v[NN];
int n,r;
int s[NN],c[NN],cur[NN],pre[NN];
bool vis[NN];

int lowbit(int x)
{
    return x&(-x);
}

void update(int x,int w)
{
    while (x<=n)
    {
        c[x]+=w;
        x+=lowbit(x);
    }
}

int getsum(int x)
{
    int ret=0;
    while (x)
    {
        ret+=c[x];
        x-=lowbit(x);
    }
    return ret;
}

int ss[NN],top;
void dfs()
{
    ss[top=1]=r;
    pre[r]=0;
    vis[r]=true;
    update(r,1);
    while (top)
    {
        int x=ss[top];
        for (int &i=cur[x]; i<v[x].size(); i++)
        {
            int y=v[x][i];
            if (!vis[y])
            {
                vis[y]=true;
                pre[y]=getsum(y-1);
                update(y,1);
                ss[++top]=y;
                break;
            }
        }
        if (cur[x]==v[x].size())
        {
            s[x]=getsum(x-1)-pre[x];
            top--;
        }
    }
}

int main()
{
    while (scanf("%d%d",&n,&r)!=EOF && n|r)
    {
        for (int i=1; i<=n; i++)
        {
            v[i].clear();
            c[i]=0;
            s[i]=0;
            vis[i]=false;
            cur[i]=0;
        }
        int x,y;
        for (int i=1; i<n; i++)
        {
            scanf("%d%d",&x,&y);
            v[x].push_back(y);
            v[y].push_back(x);
        }
        dfs();
        printf("%d",s[1]);
        for (int i=2; i<=n; i++) printf(" %d",s[i]);
        printf("\n");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值