• HDU3887 Counting Offspring 树状数组+模拟栈


    http://acm.hdu.edu.cn/showproblem.php?pid=3887

    做树状数组专题,竟然还是没有看出这题可以用树状数组来写,表示有点不好意思啊。

    原来树状数组之所以能够搞定这一题是因为我们在建立好一棵数时,通过反问一个节点的子孙们后,顺序对的变化数来统计有多少数字比该节点小的子孙节点。

    该题用DFS搜索直接爆栈,所以恶心的写了一个模拟栈,其实要注意的就是每个节点要在第一次出栈时保留在栈,第二次才从栈中出去,亦即是当其孩子节点都被反问完之后。

    这题还有一点不得不说的就是给定的边的关系没有确定,要建立一个双向的邻接表,这就相对与给定的点可以从不同的方向来看其从属关系,而给定的根节点就确定了这种关系。

    代码如下:

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <stack>
    #define INF 10000000
    #define MAXN 100005
    using namespace std;

    struct Node
    {
    int code, next;
    }edge[2*MAXN];

    int N, M, head[MAXN], tol, res[MAXN], c[MAXN], visit[MAXN];

    stack<int>stk;

    inline int lowbit(int x)
    {
    return x & -x;
    }

    inline void update(int pos, int val)
    {
    for (int i = pos; i <= N; i += lowbit(i))
    {
    c[i] += val;
    }
    }

    inline int getsum(int pos)
    {
    int s = 0;
    for (int i = pos; i > 0; i -= lowbit(i))
    s += c[i];
    return s;
    }

    void modify(int a, int b)
    {
    edge[tol].code = b;
    edge[tol].next = head[a];
    head[a] = tol++;
    }

    void dfs(int f)
    {
    int pos, code;
    stk.push(f);
    while (!stk.empty())
    {
    int pos = stk.top();
    if (visit[pos])
    {
    stk.pop();
    res[pos] = getsum(pos-1) - res[pos];
    update(pos, 1);
    }
    else
    {
    visit[pos] = 1;
    res[pos] = getsum(pos-1);
    for (int i = head[pos]; i != -1; i = edge[i].next)
    {
    code = edge[i].code;
    if (!visit[code])
    stk.push(code);
    }
    }

    }
    }

    int main()
    {
    int a, b;
    while (scanf("%d %d", &N, &M), M|N)
    {
    tol = 0;
    memset(head, -1, sizeof (head));
    memset(c, 0, sizeof (c));
    memset(visit, 0, sizeof (visit));
    for (int i = 1; i < N; ++i)
    {
    scanf("%d %d", &a, &b);
    modify(a, b);
    modify(b, a);
    }
    dfs(M);
    for (int i = 1; i <= N; ++i)
    {
    printf(i == N ? "%d\n" : "%d ", res[i]);
    }
    }
    return 0;
    }



  • 相关阅读:
    转发-》c++ stl multimap基本操作使用技巧详细介绍
    控件传递,待更新
    封装函数获取体的最大4个角
    找vector最大最小《转载》
    获取面面积,资料来自录制和网友分享
    【转】插入排序
    NXOpen获取UFUN的tag
    创建注释
    创建铜公开粗程序
    NXopen create chamfer tool
  • 原文地址:https://www.cnblogs.com/Lyush/p/2368160.html
Copyright © 2020-2023  润新知