问你对于每个节点,它的子树上标号比它小的点有多少个
子树的问题,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;
}