/*
树状数组。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;
}
HDOJ3887-DFS人工栈,树状数组
最新推荐文章于 2022-04-09 11:06:15 发布