• P3178 [HAOI2015]树上操作


    P3178 [HAOI2015]树上操作

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1: 
    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
    输出样例#1: 
    6
    9
    13

    说明

    对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不

    会超过 10^6 。

    code

    好长时间没打过树剖了,来一发练练手QWQ

    很裸的区间修改查询

    虽然第一次把每条边加了四次全WA

    顺便吐槽long long

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define lu u<<1
    #define ru u<<1|1
    using namespace std;
    
    typedef long long LL;
    const int MAXN = 2 * 1e6 + 10;
    LL cnt = 0, head[MAXN];
    LL N, M, root = 1, tim = 0, a[MAXN], b[MAXN];
    LL dep[MAXN], fat[MAXN], son[MAXN];
    LL tot[MAXN], top[MAXN], idx[MAXN];
    
    struct Edge {
        LL node, next;
    }e[MAXN];
    
    struct Tree {
        LL lef, rig, wei, siz, tag;
    }t[MAXN];
    
    inline LL read() {
        LL num = 0, f = 1; char ch = getchar();
        while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
        while (isdigit(ch)) { num = num * 10 + ch - '0'; ch = getchar(); } 
        return num * f;
    }
    
    void Add_Edge(LL x, LL y) {
        e[++cnt].next = head[x]; head[x] = cnt; e[cnt].node = y; 
    }
    
    LL dfs1(LL now, LL fa, LL de) {
        dep[now] = de;
        fat[now] = fa;
        tot[now] = 1;
        LL maxson = -1, v;
        for (LL i = head[now]; i ; i = e[i].next) {
            v = e[i].node;
            if (v == fa) continue;
            tot[now] += dfs1(v, now, de + 1);
            if (tot[v] > maxson) {
                maxson = tot[v]; 
                son[now] = v;
            }
        }
        return tot[now];
    }
    
    void dfs2(LL now, LL topf) {
        idx[now] = ++tim;
        a[tim] = b[now];
        top[now] = topf;
        if (!son[now]) return ;
        dfs2(son[now], topf);
        for (LL i = head[now]; i ; i = e[i].next)
            if (!idx[e[i].node]) 
                dfs2(e[i].node, e[i].node); 
    }
    
    void update(LL u) {
        t[u].wei = t[lu].wei + t[ru].wei;
    }
    
    void build(LL u, LL l, LL r) {
        t[u].lef = l; t[u].rig = r; t[u].siz = r - l + 1;
        if (l == r) {
            t[u].wei = a[l];
            return ; 
        }
        LL mid = (l + r) >> 1;
        build(lu, l, mid); 
        build(ru, mid + 1, r);
        update(u);
    }
    
    void pushdown(LL u) {
        if (!t[u].tag) return ;
        t[lu].wei += t[lu].siz * t[u].tag;
        t[ru].wei += t[ru].siz * t[u].tag;
        t[lu].tag += t[u].tag;
        t[ru].tag += t[u].tag;
        t[u].tag = 0;
    }
    
    void IntervalAdd(LL u, LL l, LL r, LL v) {
        if (l <= t[u].lef && t[u].rig <= r) {
            t[u].wei += t[u].siz * v;
            t[u].tag += v;
            return ; 
        }
        LL mid = (t[u].lef + t[u].rig) >> 1;
        pushdown(u);
        if (l <= mid) IntervalAdd(lu, l, r, v);
        if (r > mid)  IntervalAdd(ru, l, r, v);
        update(u);
    }
    
    void PointAdd(LL u, LL pos, LL val) {
        if (t[u].lef == t[u].rig) { 
            t[u].wei += val; 
            return ; 
        }
        pushdown(u);
        LL mid = (t[u].lef + t[u].rig) >> 1;
        if (pos <= mid) PointAdd(lu, pos, val);
        if (pos > mid) PointAdd(ru, pos, val);
        update(u);
    }
    
    LL IntervalSum(LL u, LL l, LL r) {
        if (l <= t[u].lef && t[u].rig <= r) return t[u].wei;
        LL ans = 0, mid = (t[u].lef + t[u].rig) >> 1;
        pushdown(u);
        if (l <= mid) ans += IntervalSum(lu, l, r);
        if (r > mid)  ans += IntervalSum(ru, l, r);
        return ans;
    }
    
    LL TreeSum(LL x, LL y) {
        LL ans = 0;
        while (top[x] != top[y]) {
            if (dep[top[x]] < dep[top[y]]) swap(x, y);
            ans += IntervalSum(1, idx[top[x]], idx[x]);
            x = fat[top[x]];
        }
        if (dep[x] > dep[y]) swap(x, y);
        ans += IntervalSum(1, idx[x], idx[y]);
        return ans;
    }
    
    int main() {
        memset(head, 0, sizeof (head));
        N = read(); M = read();
        for (LL i = 1; i <= N; ++ i) b[i] = read();
        LL x, y;
        for (LL i = 1; i <= N - 1; ++ i) {
            x = read(); y = read();
            Add_Edge(x, y);
            Add_Edge(y, x);
        }
        dfs1(root, 0, 1);
        dfs2(root, root);
        build(1, 1, N);
        LL kind, val;
        while (M --) {
            kind = read();
            if (kind == 1) {
                x = read(); val = read();
                PointAdd(1, idx[x], val);
            }
            else if (kind == 2) {
                x = read(); val = read();
                IntervalAdd(1, idx[x], idx[x] + tot[x] - 1, val);
            }
            else {
                x = read();
                printf("%lld
    ", TreeSum(root, x));
            }
        }
        return 0;
    }
  • 相关阅读:
    linq to entity group by 时间
    Entity Framework Core for Console
    EF Core 多个DbContext迁移命令
    .net for TCP服务端 && 客户端
    创建Windows Service
    EF Code First 快速创建
    在Docker中创建Mongo容器的后续设置
    Docker入门
    Python之collections.defaultdict
    Hough transform(霍夫变换)
  • 原文地址:https://www.cnblogs.com/hkttg/p/9387624.html
Copyright © 2020-2023  润新知