zoukankan      html  css  js  c++  java
  • 贴一下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;
    }
    直接贴代码吧……
  • 相关阅读:
    小波变换的引入,通俗易懂
    Leetcode 437. Path Sum III
    Leetcode 113. Path Sum II
    Leetcode 112 Path Sum
    Leetcode 520 Detect Capital
    Leetcode 443 String Compression
    Leetcode 38 Count and Say
    python中的生成器(generator)总结
    python的random模块及加权随机算法的python实现
    leetcode 24. Swap Nodes in Pairs(链表)
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5183992.html
Copyright © 2011-2022 走看看