zoukankan      html  css  js  c++  java
  • HDU 3966-Aragorn's Story 树链剖分+树状数组

    题目链接


    题意:有一棵树,每个节点有权值
    有三种操作:

    • I c1 c2 k 从节点c1到节点c2的路径上每个节点权值增加k
    • D c1 c2 k 从节点c1到节点c2的路径上每个节点权值减少k
    • Q i 查询节点i的权值是多少

    思路:

    • 树链剖分处理出来的链放在数组中,使用树状数组维护
    • 树状数组进行区间修改,单点查询

    树状数组区间修改,单点查询的方法:链接


    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    #include <stdlib.h>
    #include <vector>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <stack>
    #include <string>
    #include <math.h>
    #include <bitset>
    #include <ctype.h>
    #define CLR(n,b) memset(n, b, sizeof(n))
    using namespace std;
    typedef pair<int,int> P;
    typedef long long LL;
    const int INF = 0x3f3f3f3f;
    const double PI = acos(-1.0);
    const double eps = 1e-9;
    const int N = 6e4 + 5;
    const int mod = 1e9 + 7;
    struct Edge
    {
        int u,v;
        Edge() {}
        Edge(int a, int b): u(a), v(b) {}
    };
    int fa[N],son[N], p[N],fp[N], top[N],dep[N],sz[N];
    int pos;
    int n,m,k;
    vector<Edge> edges;
    vector<int> G[N];
    void init(int n)
    {
        CLR(fa, 0);  CLR(son, -1); CLR(p, -1);
        CLR(fp, -1); CLR(top, 0); CLR(sz, 0); CLR(dep, 0);
        pos = 0; edges.clear();
        for(int i = 0; i <= n; i++) G[i].clear();
    }
    void addedge(int u, int v)
    {
        edges.push_back(Edge(u,v));
        edges.push_back(Edge(v,u));
        int m = edges.size();
        G[u].push_back(m-2);
        G[v].push_back(m-1);
    }
    
    // 树链剖分
    
    void dfs(int u, int pre, int d)
    {
        fa[u] = pre;
        dep[u] = d;
        sz[u] = 1;
        son[u] = -1;
        for(int i = 0; i < G[u].size(); i++)
        {
            Edge &e = edges[G[u][i]];
            int v = e.v;
            if(v == pre) continue;
            dfs(v, u, d+1);
            sz[u] += sz[v];
            if(son[u] == -1 || sz[son[u]] < sz[v])
                son[u] = v;
        }
    }
    
    void getpos(int u, int sp)
    {
        top[u] = sp;
        p[u] = ++pos;
        fp[p[u]] = u;
        if(son[u] == -1) return;
        getpos(son[u], sp);
        for(int i = 0; i < G[u].size(); i++)
        {
            Edge &e = edges[G[u][i]];
            int v = e.v;
            if(v == son[u] || v == fa[u]) continue;
            getpos(v, v);
        }
    }
    
    // 树状数组
    int c[N];
    inline int lowbit(int x)
    {
        return x&(-x);
    }
    void add(int x, int val)
    {
        while(x <= n)
        {
            c[x] += val;
            x += lowbit(x);
        }
    }
    int sum(int x)
    {
        int ans = 0;
        while(x)
        {
            ans += c[x];
            x -= lowbit(x);
        }
        return ans;
    }
    
    // change
    void change(int x, int y, int val)
    {
        int u = x, v = y;
        int f1 = top[u], f2 = top[v];
        while(f1 != f2)
        {
            if(dep[f1] < dep[f2])
            {
                swap(f1,f2);
                swap(u,v);
            }
            add(p[f1], val);
            add(p[u]+1, -val);
            u = fa[f1];
            f1 =top[u];
        }
    
        if(dep[u] > dep[v]) swap(u,v);
        add(p[u], val);
        add(p[v]+1, -val);
    }
    
    int a[N];
    int main()
    {
        while(~scanf("%d%d%d", &n, &m, &k))
        {
            init(n);
            for(int i = 1; i <= n; i++)
            {
                scanf("%d", &a[i]);
            }
            for(int i = 0; i < m; i++)
            {
                int u,v;
                scanf("%d%d", &u, &v);
                addedge(u,v);
            }
            dfs(1,1,0);
            getpos(1,1);
            memset(c, 0, sizeof(c));
            for(int i = 1; i <= n; i++)
            {
                add(p[i], a[i]);
                add(p[i]+1, -a[i]);
            }
            while(k--)
            {
                char cmd[10];
                int x,y,z;
                scanf("%s", cmd);
                if(cmd[0] == 'Q')
                {
                    scanf("%d", &x);
                    printf("%d
    ", sum(p[x]));
                }
                else
                {
                    scanf("%d%d%d", &x,&y,&z);
                    if(cmd[0] == 'D')
                        z = -z;
                    change(x,y,z);
                }
            }
        }
    
        return 0;
    }
    
  • 相关阅读:
    [转] Optimizely:在线网站A/B测试平台
    批处理命令——choice
    批处理命令——%0
    批处理命令——call 和 start
    批处理命令——rem 和 pause
    批处理命令——goto 和 :
    PHPCMS V9 学习总结
    PHPCMS V9 环境搭建
    批处理命令——echo 和 @
    利用Qt Assistant 定制帮助文档
  • 原文地址:https://www.cnblogs.com/Alruddy/p/7492307.html
Copyright © 2011-2022 走看看