Problem Description
You are given a tree, it’s root is p, and the node is numbered from 1 to n. Now define f(i) as the number of nodes whose number is less than i in all the succeeding nodes of node i. Now we need to calculate f(i) for any possible i.
Input
Multiple cases (no more than 10), for each case:
The first line contains two integers n (0 < n < =10^5) and p, representing this tree has n nodes, its root is p.
Following n-1 lines, each line has two integers, representing an edge in this tree.
The input terminates with two zeros.
Output
For each test case, output n integer in one line representing f(1), f(2) … f(n), separated by a space.
Sample Input
15 7
7 10
7 1
7 9
7 3
7 4
10 14
14 2
14 13
9 11
9 6
6 5
6 8
3 15
3 12
0 0
Sample Output
0 0 0 0 0 1 6 0 3 1 0 0 0 2 0
http://www.cnblogs.com/kane0526/archive/2013/01/10/2855125.html
题目大意: 给你一颗n个节点的数,对于每个节点i,问你每个节点的子树中有
多少个节点序列数小于i,求f[i]。
解题思路:
用样例来说明,我们可以先深搜一遍,那么dfs序就是:7, 10, 14, 2 ,2 ,13, 13, 14, 10, 1, 1 … …
对这个序列进行分析可以发现,举例:14, 2 ,2 ,13, 13, 14 , 节点14中间的数就是它的子树序列。
dfs打好序列后就对序列进行遍历一遍,开两个st[], sd[] 数组, 存每个节点开始和结束位置。接下来就是树状数组求和,注意这里要序列从大到小求和(也就是n–>1),求完后删掉对应位置的数,树状数组进行相应的更新操作。
//从大到小机智,从15开始,其他数都比它小,因此用每个数都是1,就是求和。接着将15划掉,那么左14到右14中间的数都比它小,因此求和。
for(int i=n; i>=1; i--)
{
f[i]=(getsum(sd[i]-1)-getsum(st[i]))/2;
cal(st[i],-1);
cal(sd[i],-1);
}
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
const int maxn=100005;
vector<int>vt[maxn];
int bit[2*maxn];
int que[2*maxn];//<2倍
int st[maxn];
int sd[maxn];
int f[maxn];
int n, rt, num;
void dfs(int u, int fa)
{
que[++num]=u;
for(int i=0; i<vt[u].size(); i++)//
{
int v=vt[u][i];
if(v==fa) continue;
dfs(v,u);
} //
que[++num]=u;
}
int lowbit(int x)
{
return x&(-x);
}
void cal(int x, int val)
{
while(x<=num)
{
bit[x]+=val;
x+=lowbit(x);
}
}
int getsum(int x)
{
int ans=0;
while(x>0)
{
ans+=bit[x];
x-=lowbit(x);
}
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&rt),n+rt)
{
for(int i=0; i<=n; i++)
vt[i].clear();
for(int i=1; i<n; i++)
{
int x, y;
scanf("%d%d",&x,&y);
vt[x].push_back(y);
vt[y].push_back(x);
}
fill(st+1,st+1+n,0);
num=0;
dfs(rt,-1);
for(int i=1; i<=num; i++)//....
{
if(!st[que[i]]) st[que[i]]=i;
else sd[que[i]]=i;
}
memset(bit,0,sizeof(bit));
for(int i=1; i<=num; i++)
cal(i,1);//每个数都是1
for(int i=n; i>=1; i--)
{
f[i]=(getsum(sd[i]-1)-getsum(st[i]))/2;
cal(st[i],-1);
cal(sd[i],-1);
}
printf("%d",f[1]);
for(int i=2; i<=n; i++)
printf(" %d",f[i]);
puts("");
}
return 0;
}