HDU 3887 Counting Offspring [DFS序列+树状数组]

Counting Offspring

Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 423    Accepted Submission(s): 137


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
 

Author
bnugong
 

Source


题意是,给一棵树,给每个结点一个标号,问所有存在的结点,它的子树中,结点标号小于它的有多少个。

做法:DFS序列构造+树状数组查询区间。

竟然忘了DFS的遍历的意义。对一棵树进行DFS遍历,一个结点最多到达两次,一次出,一次入,而这之间的结点标号均为它的子树结点的标号。所以只要用某种方法快速查询其左右标号内含的区间中,比它小的标号个数即可。(别*2)在肖神的提携下,ym到了树状数组在本题的使用方法。

做法流程。初始化(记得树状数组和DFS记录序列要开点数*2的。。因为这个nc半天,不解释。) ->建图-> DFS(因为HDU坑爹的栈大小,必须手写栈模拟DFS才能过。。第一次手工模拟DFS。。太蛋疼了。。调了无数次。)->对于每个点查询DFS序列。(既然是离线查询,那么就按照从小到大查吧。凡事要有个序,有序了就好查了。对于每个点的标号,先查它的左右区间是否有比它小的sum(r[i] - 1) - sum(l[i]]).....再把它插入树状数组中,插一次就好,不然结果还得除二。(都是肖神!)
T_T。。记得树状数组和dfs序列都是开到点数*2的,而其他的都是点数大小的。注意初始化和树状数组查询和更新时的范围同理。
代码:
#include <iostream>
#include 
<cstdio>
#include 
<cstring>
#include 
<stack>
#include 
<algorithm>
using namespace std;
stack 
<int> S;
#define maxn 100005
int cnt,p,n,tot,lit[maxn],seq[maxn * 2],l[maxn],r[maxn],tr[maxn * 2];
int bit(int x){return x & -x;}
bool vis[maxn];
struct edge
{
    
int p,next;
    edge(){}
    edge(
int a,int b):p(a),next(b){}
}v[maxn],e[maxn 
* 2];
void add(int p,int q)
{
    e[tot] 
= edge(q,v[p].next);
    v[p].next 
= tot++;
}
int sum(int x)
{
    
int ans = 0;
    
for(;x > 0;x -= bit(x))
        ans 
+= tr[x];
    
return ans;
}
void mod(int x,int val)
{
    
for(;x < cnt;x += bit(x))
        tr[x] 
+= val;    
}
void init()
{
    tot 
= 0;
    
for(int i = 1;i <= n;i++)
        v[i].next 
= -1;
    fill(tr,tr 
+ 2 * n + 1,0);
    fill(vis,vis 
+ n + 1,0);
    
while(!S.empty())
        S.pop();
}
void dfs()
{
    cnt 
= 1;
    S.push(p);
    
while(!S.empty())
    {
        
int now = S.top();
        
if(!vis[now])
        {
            seq[cnt] 
= now;
            l[now] 
= cnt++;
            vis[now] 
= true;
        }
        
bool mark = false;
        
for(int k = v[now].next;~k;k = e[k].next)
        {
            
if(!vis[e[k].p])
            {
                mark 
= true;
                S.push(e[k].p);
                v[now].next 
= e[k].next;
                
break;
            }
        }
        
if(mark)
            
continue;
        
if(vis[now])
        {
            seq[cnt] 
= now;
            r[now] 
= cnt++;
            S.pop();
        }
    }
}
void gao()
{
    
for(int i = 1;i <= n;i++)
    {
        lit[i] 
= sum(r[i] - 1- sum(l[i]);
        mod(l[i],
1);
    }
}
int main()
{
    
while(scanf("%d %d",&n,&p) == 2 && (p || n))
    {
        init();
        
for(int i = 0;i < n - 1;i++)
        {
            
int a,b;
            scanf(
"%d %d",&a,&b);
            add(a,b);
            add(b,a);
        }
        dfs();
        gao();
        
for(int i = 1;i <= n;i++)
        {
            printf(
"%d",lit[i]);
            putchar((i 
== n)?'\n':' ');
        }
    }
}

posted on 2011-07-28 00:47 BUPT-[aswmtjdsj] @ Penalty 阅读(857) 评论(0)  编辑 收藏 引用 所属分类: 数据结构HDU Solution Report 树状结构


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2011年9月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

导航

统计

常用链接

留言簿(1)

随笔分类(150)

随笔档案(71)

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜