• [CF383C] Propagating tree


    Description

    给定一棵有根树,每次操作一个结点(将它加上 (v),孩子减去 (v),孩子的孩子加上 (v),以此类推),或者查询一个结点的值。

    Solution

    考虑维护两个序列,一个序列中所有深度为奇数的点是有效的,另一个序列中所有深度为偶数的点是有效的。如果操作的一个点是奇数深度的,那么就在前者中加,后者中减,若是偶数深度则恰好相反。当我们取出一个点的权值的时候,根据它是奇数深度的点还是偶数深度的点到对应的序列中取即可。

    通过 DFS 序转化为区间操作单点询问,再通过差分转化为单点修改区间询问,于是用树状数组处理即可。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    const int N = 1000005;
    
    struct BIT
    {
        vector<int> a;
        int size;
        BIT(int size) : size(size)
        {
            a.resize(size + 2);
        }
        int lowbit(int i)
        {
            return i & (-i);
        }
        void add(int i, int v)
        {
            while (i <= size)
            {
                a[i] += v;
                i += lowbit(i);
            }
        }
        int sum(int i)
        {
            int ans = 0;
            while (i > 0)
            {
                ans += a[i];
                i -= lowbit(i);
            }
            return ans;
        }
    
        void Modify(int l, int r, int v)
        {
            add(l, v);
            add(r + 1, -v);
        }
    
        int Query(int r)
        {
            return sum(r);
        }
    };
    
    vector<int> g[N];
    int dep[N], vis[N], dfn[N], fin[N], ind;
    
    void dfs(int p)
    {
        dfn[p] = ++ind;
        vis[p] = 1;
        for (int q : g[p])
        {
            if (vis[q] == 0)
            {
                dep[q] = dep[p] + 1;
                dfs(q);
            }
        }
        fin[p] = ind;
    }
    
    signed main()
    {
        int n, m;
        cin >> n >> m;
    
        BIT *bit[2];
        bit[0] = new BIT(n);
        bit[1] = new BIT(n);
    
        vector<int> a(n + 2);
        for (int i = 1; i <= n; i++)
            cin >> a[i];
    
        for (int i = 1; i < n; i++)
        {
            int u, v;
            cin >> u >> v;
            g[u].push_back(v);
            g[v].push_back(u);
        }
    
        dfs(1);
    
        for (int i = 1; i <= n; i++)
        {
            bit[0]->Modify(dfn[i], dfn[i], a[i]);
            bit[1]->Modify(dfn[i], dfn[i], a[i]);
        }
    
        for (int i = 1; i <= m; i++)
        {
            int t1, t2, t3;
            cin >> t1 >> t2;
            if (t1 == 1)
            {
                cin >> t3;
                bit[dep[t2] & 1]->Modify(dfn[t2], fin[t2], t3);
                bit[(dep[t2] & 1) ^ 1]->Modify(dfn[t2], fin[t2], -t3);
            }
            else
            {
                cout << bit[dep[t2] & 1]->Query(dfn[t2]) << endl;
            }
        }
    }
    
  • 相关阅读:
    Android入门程序(ListView包括一个网络状态显示)
    shell
    android.os.NetworkOnMainThreadException
    apache虚拟主机名不区分大小写的解决办法
    QT制作全屏播放器以及出现的问题
    QT使用Q_OBJECT链接不通过的一种情况
    使用PHP返回需要登录验证的HTML页面
    怎么样得到Boost的options_description的描述字符串
    QT的QHttp无信号发出,窗口程序关闭时崩溃
    apache 配置https
  • 原文地址:https://www.cnblogs.com/mollnn/p/14119249.html
Copyright © 2020-2023  润新知