http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=21535
题目大意: 给你一颗n个节点的数,对于每个节点i,问你每个节点的子树中有多少个节点序列数小于i,求f[i]。
先跑一遍dfs,得到dfs序,
树状数组初始化为空
然后我们从 节点编号1遍历到n
对于每个节点编号i,查询 【in[i]-1,out[i]】的sum,便是f[i]
然后我们updata(in[i])的值为1,也就是 在 点i对应dfs序中的位置标1,
下次别的节点y在get_sum时,如果当前点i 在 y节点的管辖范围内,那么 便算作 一个 节点编号小于y的 子节点
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <iostream>
using namespace std;
__int64 inf=15;
double eps=0.000001;
int n,m;
vector < vector<int> > mp(100000+50);
int id;
int in[100000+50],out[100000+50];
int tree[100000+5];
int vis[100000+50];
void dfs1(int x)
{
in[x]=++id;
vis[x]=1;
// who[id]=x;
int i;
for (i=0;i<mp[x].size();i++)
{
int v=mp[x][i];
if (vis[v]) continue;
dfs1(v);
}
out[x]=id;
}
int lowbit(int x)
{return x&-x;}
void add(int x,int val)
{
for (int i=x;i<=n;i=i+lowbit(i))
tree[i]+=val;
}
int get(int x)
{
int sum=0,i;
for (i=x;i;i-=lowbit(i))
sum+=tree[i];
return sum;
}
int main()
{
int x,y,i,rt;
while(cin>>n>>rt)
{
id=0;
if (!n&&!rt) break;
memset(tree,0,sizeof(tree));
memset(vis,0,sizeof(vis));
for (i=1;i<=n;i++)
mp[i].clear();
for (i=1;i<=n-1;i++)
{
scanf("%d%d",&x,&y);
mp[x].push_back(y);
mp[y].push_back(x);
}
dfs1(rt);
int line=1;
for (i=1;i<=n;i++)
{
int ret= get(out[i])-get(in[i]-1);
if (!line) printf(" ");
printf("%d",ret);
line=0;
add(in[i],1);
}
printf("\n");
}
return 0;
}