HDU-3887-Counting Offspring-dfs序+树状数组

来源:互联网 发布:皇室战争淘宝慢充原理 编辑:程序博客网 时间:2024/05/20 14:23

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;}



0 0
原创粉丝点击