zoukankan      html  css  js  c++  java
  • 【bzoj4034】[HAOI2015]T2

    *题目描述:
    有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
    操作,分为三种:
    操作 1 :把某个节点 x 的点权增加 a 。
    操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
    操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

    *输入:
    第一行包含两个整数 N, M 。表示点数和操作数。
    接下来一行 N 个整数,表示树中节点的初始权值。
    接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。
    再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操
    作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。

    *输出:
    对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

    *样例输入:
    5 5
    1 2 3 4 5
    1 2
    1 4
    2 3
    2 5
    3 3
    1 2 1
    3 5
    2 1 2
    3 3

    *样例输出:
    6
    9
    13

    *提示:
    对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不
    会超过 10^6 。

    *题解:
    树链剖分套线段树。

    *代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    
    #ifdef WIN32
        #define LL "%I64d"
    #else
        #define LL "%lld"
    #endif
    
    #ifdef CT
        #define debug(...) printf(__VA_ARGS__)
        #define setfile() 
    #else
        #define debug(...)
        #define filename ""
        #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout)
    #endif
    
    #define R register
    #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
    #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
    #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
    #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
    #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
    #define cabs(_x) ((_x) < 0 ? (- (_x)) : (_x))
    char B[1 << 15], *S = B, *T = B;
    inline int F()
    {
        R char ch; R int cnt = 0; R bool minus = 0;
        while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
        ch == '-' ? minus = 1 : cnt = ch - '0';
        while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
        return minus ? -cnt : cnt;
    }
    #define maxn 100010
    typedef long long ll;
    int val[maxn];
    struct Edge
    {
        Edge *next;
        int to;
    }*last[maxn], e[maxn << 1], *ecnt = e;
    inline void link(R int a, R int b)
    {
        *++ecnt = (Edge) {last[a], b}; last[a] = ecnt;
        *++ecnt = (Edge) {last[b], a}; last[b] = ecnt;
    }
    bool vis[maxn];
    int size[maxn], fa[maxn], top[maxn], dep[maxn], son[maxn], dfn[maxn], pos[maxn], timer;
    int maxson[maxn];
    void dfs1(R int x)
    {
        vis[x] = 1; size[x] = 1;
        for (R Edge *iter = last[x]; iter; iter = iter -> next)
        {
            R int pre = iter -> to;
            if (vis[pre]) continue;
            dep[pre] = dep[x] + 1;
            fa[pre] = x;
            dfs1(pre);
            size[x] += size[pre];
            size[pre] > size[son[x]] ? son[x] = pre : 0;
        }
    }
    void dfs2(R int x)
    {
        vis[x] = 0; top[x] = x == son[fa[x]] ? top[fa[x]] : x;
        dfn[x] = ++timer; pos[timer] = x;
        son[x] ? dfs2(son[x]), 0 : 0;
        for (R Edge *iter = last[x]; iter; iter = iter -> next)
            if (vis[iter -> to]) dfs2(iter -> to);
        maxson[x] = timer;
    }
    ll tr[maxn << 2], tag[maxn << 2];
    int ql, qr, a;
    #define ls (o << 1)
    #define rs (o << 1 | 1)
    #define mid ((l + r) >> 1)
    #define update() (tr[o] = tr[ls] + tr[rs])
    inline void pushdown(R int o, R int l, R int r)
    {
        if (tag[o] != 0 && l < r)
        {
            R ll tmp = tag[o];
            tag[ls] += tmp;
            tag[rs] += tmp;
            tr[ls] += 1ll * (mid - l + 1) * tmp;
            tr[rs] += 1ll * (r - mid) * tmp;
            tag[o] = 0;
        }
    } 
    void build(R int o, R int l, R int r)
    {
        if (l == r)
        {
            tr[o] = val[pos[l]];
            return ;
        }
        build(ls, l, mid);
        build(rs, mid + 1, r);
        update();
    }
    void add(R int o, R int l, R int r)
    {
        if (ql <= l && r <= qr)
        {
            tag[o] += a;
            tr[o] += 1ll * (r - l + 1) * a;
            return;
        }
        pushdown(o, l, r);
        if (ql <= mid) add(ls, l, mid);
        if (mid < qr) add(rs, mid + 1, r);
        update();
    }
    ll query(R int o, R int l, R int r)
    {
        if (ql <= l && r <= qr) return tr[o];
        pushdown(o, l, r);
        R ll ret = 0;
        if (ql <= mid) ret += query(ls, l, mid);
        if (mid < qr) ret += query(rs, mid + 1, r);
        return ret;
    }
    int main()
    {
    //  setfile();
        R int n = F(), m = F();
        for (R int i = 1; i <= n; ++i) val[i] = F();
        for (R int i = 1; i < n; ++i) link(F(), F());
        dfs1(1); dfs2(1);
        build(1, 1, n);
        for (; m; --m)
        {
            R int opt = F(), x;
            if (opt == 1)
            {
                x = F(); a = F();
                ql = dfn[x]; qr = dfn[x];
                add(1, 1, n);
            }
            else if (opt == 2)
            {
                x = F(); a = F();
                ql = dfn[x]; qr = maxson[x];
                add(1, 1, n);
            }
            else
            {
                x = F(); R ll ans = 0;
                while (x)
                {
                    ql = dfn[top[x]]; qr = dfn[x];
                    ans += query(1, 1, n);
                    x = fa[top[x]];
                }
                printf("%lld
    ", ans );
            }
        }
        return 0;
    }
    
  • 相关阅读:
    为函数的参数指定类型
    装饰器函数导致的原函数的元数据被替代--保存元数据
    ssm单项目整合
    security权限控制
    springAOP学习笔记
    springIOC学习笔记
    springDataJpa学习笔记
    springmvc学习笔记
    原生mybaits学习笔记
    java反射和注解
  • 原文地址:https://www.cnblogs.com/cocottt/p/6764974.html
Copyright © 2011-2022 走看看