[BZOJ4034][HAOI2015]树上操作

4034: [HAOI2015]树上操作

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 5752  Solved: 1850
[Submit][Status][Discuss]

Description

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

Input

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

Output

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

 

Sample Input

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

Sample Output

6
9
13

HINT

 

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

 

裸的树剖

在划分轻重链时处理dfs序

#include <cstdio>
#include <algorithm>
using namespace std;
char buf[10000000], *ptr = buf - 1;
inline int readint(){
    int n = 0;
    bool flag = false;
    while(*++ptr < '0' || *ptr > '9') if(*ptr == '-') flag = true;
    while(*ptr >= '0' && *ptr <= '9') n = (n << 1) + (n << 3) + (*ptr++ & 15);
    return flag ? -n : n; 
}
typedef long long ll;
const int maxn = 100000 + 10;
int n, m;
struct Edge{
    int to, next;
    Edge(){}
    Edge(int _t, int _n): to(_t), next(_n){}
}e[maxn * 2];
int fir[maxn] = {0}, cnt = 0;
inline void ins(int u, int v){
    e[++cnt] = Edge(v, fir[u]); fir[u] = cnt;
    e[++cnt] = Edge(u, fir[v]); fir[v] = cnt;
}
int fa[maxn], siz[maxn], son[maxn];
void dfs1(int u){
    siz[u] = 1;
    son[u] = 0;
    for(int v, i = fir[u]; i; i = e[i].next){
        v = e[i].to;
        if(v == fa[u]) continue;
        fa[v] = u;
        dfs1(v);
        siz[u] += siz[v];
        if(!son[u] || siz[v] > siz[son[u]]) son[u] = v;
    }
}
int val[maxn], w[maxn], top[maxn], in[maxn], out[maxn], dfs_idx = 0;
void dfs2(int u){
    in[u] = ++dfs_idx;
    w[dfs_idx] = val[u];
    if(!son[u]){
        out[u] = dfs_idx;
        return;
    }
    top[son[u]] = top[u];
    dfs2(son[u]);
    for(int v, i = fir[u]; i; i = e[i].next){
        v = e[i].to;
        if(v == fa[u] || v == son[u]) continue;
        top[v] = v;
        dfs2(v);
    }
    out[u] = dfs_idx;
}
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
ll sum[maxn * 4], tag[maxn * 4] = {0};
inline void pushup(int rt){
    sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
void build(int l, int r, int rt){
    if(l == r) sum[rt] = w[l];
    else{
        int mid = l + r >> 1;
        build(lson);
        build(rson);
        pushup(rt);
    }
}
inline void pushdown(int rt, int m){
    if(tag[rt]){
        sum[rt << 1] += tag[rt] * (m - (m >> 1));
        sum[rt << 1 | 1] += tag[rt] * (m >> 1);
        tag[rt << 1] += tag[rt];
        tag[rt << 1 | 1] += tag[rt];
        tag[rt] = 0;
    }
}
int ql, qr, qv;
inline void update(int l, int r, int rt){
    if(ql <= l && r <= qr){
        sum[rt] += (ll)qv * (r - l + 1);
        tag[rt] += qv;
    }
    else{
        pushdown(rt, r - l + 1);
        int mid = l + r >> 1;
        if(ql <= mid) update(lson);
        if(qr > mid) update(rson);
        pushup(rt);
    }
}
inline ll query(int l, int r, int rt){
    if(ql <= l && r <= qr) return sum[rt];
    else{
        pushdown(rt, r - l + 1);
        int mid = l + r >> 1;
        ll ret = 0;
        if(ql <= mid) ret += query(lson);
        if(qr > mid) ret += query(rson);
        return ret;
    }
}
inline void ask(){
    int x = readint();
    ll ans = 0;
    while(top[x] != 1){
        ql = in[top[x]];
        qr = in[x];
        ans += query(1, n, 1);
        x = fa[top[x]];
    }
    ql = in[1];
    qr = in[x];
    ans += query(1, n, 1);
    printf("%lld\n", ans);
}
int main(){
    buf[fread(buf, sizeof(char), sizeof(buf), stdin)] = 0;
    n = readint();
    m = readint();
    for(int i = 1; i <= n; i++) val[i] = readint();
    for(int i = 1; i < n; i++) ins(readint(), readint());
    fa[1] = 0;
    dfs1(1);
    top[1] = 1;
    dfs2(1);
    build(1, n, 1);
    int opt, x;
    while(m--){
        opt = readint();
        if(opt == 1){
            x = readint();
            ql = qr = in[x];
            qv = readint();
            update(1, n, 1);
        }
        else if(opt == 2){
            x = readint();
            ql = in[x];
            qr = out[x];
            qv = readint();
            update(1, n, 1);
        }
        else ask();
    }
    return 0;
} 

 

posted @ 2017-10-14 23:43  Elder_Giang  阅读(122)  评论(0编辑  收藏  举报