HDU3887(树dfs序列+树状数组)

Counting Offspring

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

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

思路: 入栈前数目-入栈后数目.c++可调整栈的大小.#pragma comment(linker,"/STACK:100000000,100000000") 两个100000000均为字节数。

#pragma comment(linker,"/STACK:100000000,100000000")
#include <cstdio>
#include <string.h>
using namespace std;
const int MAXN=100005;
struct Edge{
    int to,net;
}es[MAXN+MAXN];
int head[MAXN],tot;
void addedge(int u,int v)
{
    es[tot].to=v;
    es[tot].net=head[u];
    head[u]=tot++;
    es[tot].to=u;
    es[tot].net=head[v];
    head[v]=tot++;
}
int bit[MAXN];
int n,root;
void add(int i,int x)
{
    while(i<MAXN)
    {
        bit[i]+=x;
        i+=(i&(-i));
    }
}
int sum(int i)
{
    int s=0;
    while(i>0)
    {
        s+=bit[i];
        i-=(i&(-i));
    }
    return s;
}
int res[MAXN],tmp[MAXN];
void dfs(int u,int fa)
{
    tmp[u]=sum(u-1);
    for(int i=head[u];i!=-1;i=es[i].net)
    {
        int v=es[i].to;
        if(v!=fa)
        {
            add(v,1);
            dfs(v,u);
        }
    }
    res[u]=sum(u-1)-tmp[u];
}
int main()
{
    while(scanf("%d%d",&n,&root)!=EOF&&(n||root))
    {
        memset(head,-1,sizeof(head));
        memset(bit,0,sizeof(bit));
        tot=0;
        for(int i=0;i<n-1;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u,v);
        }
        dfs(root,-1);
        for(int i=1;i<n;i++)
        {
            printf("%d ",res[i]);
        }
        printf("%d\n",res[n]);
    }
    return 0;
}
时间: 2024-11-08 18:24:54

HDU3887(树dfs序列+树状数组)的相关文章

【Codeforces163E】e-Government AC自动机fail树 + DFS序 + 树状数组

E. e-Government time limit per test:1 second memory limit per test:256 megabytes input:standard input output:standard output The best programmers of Embezzland compete to develop a part of the project called "e-Government" — the system of automa

【BZOJ-2434】阿狸的打字机 AC自动机 + Fail树 + DFS序 + 树状数组

2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2022  Solved: 1158[Submit][Status][Discuss] Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的:l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最

hust1350Trie【字典树+dfs || 字典树 + LCA】

大意:告诉你一些字符串 让你组成字典树, 然后定义每个节点到所有叶子节点的距离的和等于改点的value 当根节点只有一个孩子,该根节点也算一个叶子节点 问所有节点的value的最小值 分析: 开始做的时候  就想的是   枚举每个点  然后求它到所有叶子节点的和  求任意两点的最近距离  用公共祖先来求 于是就有了这个算法 需要预处理出来所有的叶子节点 不能单纯的用字典树的flag来记录  例如插入aaa aa a  那么 a  aa aaa 都会被当成叶子节点 对于这里的处理 我是排了一次序

P2633|主席树+dfs序+树链剖分求lca+离散化

不知道为什么会RE.. 待补 思路:链上求u和v两点路径第k小利用lca就转变为了 U+V-LCA-FA(LCA) 上的第k小,这因为每个点的主席树的root是从其父转移来的.可以用树链剖分求lca:在dfs序上建立主席树将树上问题转变为区间问题,询问的时候用主席树求区间k小值. 终于能写出这种题了,开心! #include<bits/stdc++.h> using namespace std; const int maxn = 1e5+100; int n,m,e = 1,num,ans=0

POJ 2763 Housewife Wind(DFS序+LCA+树状数组)

Housewife Wind Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 11419   Accepted: 3140 Description After their royal wedding, Jiajia and Wind hid away in XX Village, to enjoy their ordinary happy life. People in XX Village lived in beauti

[bzoj3155]Preprefix sum(树状数组)

3155: Preprefix sum Time Limit: 1 Sec  Memory Limit: 512 MBSubmit: 1183  Solved: 546[Submit][Status][Discuss] Description Input 第一行给出两个整数N,M.分别表示序列长度和操作个数 接下来一行有N个数,即给定的序列a1,a2,....an 接下来M行,每行对应一个操作,格式见题目描述 Output 对于每个询问操作,输出一行,表示所询问的SSi的值. Sample In

HDU 1166 —— 敌兵布阵 【树状数组 or 线段树】

http://acm.hdu.edu.cn/showproblem.php?pid=1166 需求: 1.点修改 2.区间求和 标准的BIT(二叉索引树,又名树状数组)问题,当然也可以用最基础的仅支持“点修改”的线段树来解决! 线段树版本: #include <cstdio> #include <iostream> #define INF 0x3f3f3f3f using namespace std; const int MAXN = 65536 + 5; // 65536 是最小

HDU 5692 线段树+dfs序

Snacks Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1779    Accepted Submission(s): 427 Problem Description 百度科技园内有n 个零食机,零食机之间通过n−1 条路相互连通.每个零食机都有一个值v ,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充,零食机的价值v

二分索引树与线段树分析

二分索引树是一种树状数组,其全名为Binary Indexed Tree.二分索引树可以用作统计作用,用于计某段连续区间中的总和,并且允许我们动态变更区间中存储的值.二分索引树和线段树非常相似,二者都享有相同的O(log2(n))时间复杂度的更新操作和O(log2(n))时间复杂度的查询操作,区别在于二分索引树更加简洁高效,而线段树则较冗杂低效,原因在于对二分索引树的操作中是使用了计算机中整数存储的特性来进行加速,而线段树中由于使用的是比较操作,因此性能不及二分索引树.那么为什么我们不抛弃线段树