• 贴一下WC总结里提到的那道裸题吧。。。


    [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 <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    using namespace std;
     
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *tail;
    inline char Getchar() {
        if(Head == tail) {
            int l = fread(buffer, 1, BufferSize, stdin);
            tail = (Head = buffer) + l;
        }
        return *Head++;
    }
    int read() {
        int x = 0, f = 1; char c = Getchar();
        while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
        while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
        return x * f;
    }
     
    #define maxn 100010
    #define maxm 200010
    #define LL long long
    int n, q, m, head[maxn], next[maxm], to[maxm], V[maxn];
     
    void AddEdge(int a, int b) {
        to[++m] = b; next[m] = head[a]; head[a] = m;
        swap(a, b);
        to[++m] = b; next[m] = head[a]; head[a] = m;
        return ;
    }
     
    int siz[maxn], fa[maxn], son[maxn], w[maxn], ww, top[maxn], val[maxn];
    void dfs(int u) {
        siz[u] = 1;
        for(int e = head[u]; e; e = next[e]) if(to[e] != fa[u]) {
            fa[to[e]] = u;
            dfs(to[e]);
            siz[u] += siz[to[e]];
            if(siz[son[u]] < siz[to[e]]) son[u] = to[e];
        }
        return ;
    }
    void build(int u, int tp) {
        w[u] = ++ww; top[u] = tp;
        if(son[u]) build(son[u], tp);
        for(int e = head[u]; e; e = next[e]) if(to[e] != fa[u] && to[e] != son[u])
            build(to[e], to[e]);
        return ;
    }
     
    LL sumv[maxn<<2], addv[maxn<<2];
    void build(int L, int R, int o) {
        if(L == R) sumv[o] = val[L];
        else {
            int M = L + R >> 1, lc = o << 1, rc = lc | 1;
            build(L, M, lc);
            build(M+1, R, rc);
            sumv[o] = sumv[lc] + sumv[rc];
        }
        return ;
    }
    int ql, qr;
    LL v;
    void update(int L, int R, int o) {
        if(ql <= L && R <= qr) addv[o] += v;
        else {
            int M = L + R >> 1, lc = o << 1, rc = lc | 1;
            if(ql <= M) update(L, M, lc);
            if(qr > M) update(M+1, R, rc);
            sumv[o] = sumv[lc] + addv[lc] * (M - L + 1);
            sumv[o] += sumv[rc] + addv[rc] * (R - M);
        }
        return ;
    }
    LL query(int L, int R, int o, LL Add) {
        Add += addv[o];
        if(ql <= L && R <= qr) return sumv[o] + Add * (R - L + 1);
        int M = L + R >> 1, lc = o << 1, rc = lc | 1;
        LL ans = 0;
        if(ql <= M) ans += query(L, M, lc, Add);
        if(qr > M) ans += query(M+1, R, rc, Add);
        return ans;
    }
     
    LL query(int u) {
        int f = top[u]; LL ans = 0;
        while(u) {
            ql = w[f]; qr = w[u];
            ans += query(1, n, 1, 0);
            u = fa[f]; f = top[u];
        }
        return ans;
    }
     
    int main() {
        n = read(); q = read();
        for(int i = 1; i <= n; i++) V[i] = read();
        for(int i = 1; i < n; i++) AddEdge(read(), read());
         
        dfs(1);
        build(1, 1);
        for(int i = 1; i <= n; i++) val[w[i]] = V[i];
        build(1, n, 1);
        while(q--) {
            int tp = read(), u = read();
            if(tp == 1) {
                v = read(); ql = qr = w[u];
                update(1, n, 1);
            } else if(tp == 2) {
                v = read(); ql = w[u]; qr = ql + siz[u] - 1;
                update(1, n, 1);
            } else printf("%lld
    ", query(u));
        }
         
        return 0;
    }
    直接贴代码吧……
  • 相关阅读:
    dolphin以root身份打开
    linux ACL权限
    PIT中断与外设时钟配置
    GPT定时器定时
    I.MX RT 时钟控制模块(CCM)
    OLED屏显示功能的实现
    RT1052 A/D数据采集
    滴答时钟与延时
    局域网 访问mac前端项目
    js 加减乘除取余运算
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5183992.html
Copyright © 2020-2023  润新知