记录编号 416373 评测结果 AAAAAAAAAA
题目名称 [HAOI 2015]树上操作 最终得分 100
用户昵称 GravatarHeHe 是否通过 通过
代码语言 C++ 运行时间 0.716 s
提交时间 2017-06-21 13:09:21 内存使用 6.38 MiB
显示代码纯文本
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const long long MAXN = 1e5 + 10;

inline char getc(void){
    static char buf[1 << 18], *fs, *ft;
    return (fs == ft && (ft = (fs = buf) + fread(buf, 1, 1 << 18, stdin)), fs == ft) ? EOF : *fs++;
}

inline long long in(void){
    register long long res = 0, f = 1;
    register char tmp = getc();
    while(!isdigit(tmp) && tmp ^ '-') tmp = getc();
    if(tmp == '-') f = -1, tmp = getc();
    while(isdigit(tmp))
        res = (res + (res << 2) << 1) + (tmp ^ 48),
        tmp = getc();
    return res * f;
}

struct EDGE{
    long long to;
    EDGE *ne;

    EDGE(){;}
    EDGE(long long _to, EDGE *_ne){
        to = _to, ne = _ne;
    }
};

struct NODE{
    long long sum, tag;
    NODE *ls, *rs;

    NODE(){
        ls = rs = NULL;
        tag = 0;
    }
};

inline void add_edge(long long fr, long long to);
void dfs(long long u);
void dfs(long long u, long long tp);
NODE* Build(long long l, long long r);
void update(NODE *node, long long l, long long r, long long k, long long L, long long R);
long long Query(NODE *node, long long l, long long r, long long L, long long R);

NODE *root;
EDGE *head[MAXN];
long long val[MAXN];
long long fa[MAXN], siz[MAXN];
long long top[MAXN], fat[MAXN];
long long dfn[MAXN], id[MAXN];
bool visit[MAXN];
long long opt, arg;
long long N, M;

int main(){ 
#ifndef LOCAL
    freopen("haoi2015_t2.in", "r", stdin);
    freopen("haoi2015_t2.out", "w", stdout);
#endif
    memset(visit, 0x00, sizeof(visit));

    N = in(), M = in();
    for(long long i = 1; i <= N; ++i) val[i] = in();
    for(long long i = 1; i < N; ++i){
        add_edge(in(), in());
    }

    dfs(1);
    dfs(1, 1);

    root = Build(1, N);

    for(long long i = 1; i <= M; ++i){
        opt = in(), arg = in();
        if(opt == 1) update(root, dfn[arg], dfn[arg], in(), 1, N);
        else if(opt == 2) update(root, dfn[arg], dfn[arg] + siz[arg] - 1, in(), 1, N);
        else if(opt == 3){
            register long long res = 0;
            register long long tp = top[arg];

            while(tp ^ 1){
                res += Query(root, dfn[tp], dfn[arg], 1, N);
                arg = fa[tp];
                tp = top[arg];
            }

            printf("%lld\n", Query(root, dfn[1], dfn[arg], 1, N) + res);
        }
    }

    return 0;
}

inline void add_edge(long long fr, long long to){
    static EDGE *edge;
    edge = new EDGE(to, head[fr]), head[fr] = edge;
    edge = new EDGE(fr, head[to]), head[to] = edge;
    return ;
}

void dfs(long long u){
    visit[u] = true;
    siz[u] = 1;
    register long long v;

    for(register EDGE *e = head[u]; e; e = e->ne){
        if(visit[v = e->to]) continue;
        fa[v] = u;
        dfs(v);
        siz[u] += siz[v];

        if(siz[fat[u]] < siz[v]) fat[u] = v;
    }

    return ;
}

void dfs(long long u, long long tp){
    static long long cnt = 0;
    register long long v;
    id[dfn[u] = ++cnt] = u;
    top[u] = tp;

    if(!fat[u]) return ;
    dfs(fat[u], tp);
    
    for(register EDGE *e = head[u]; e; e = e->ne){
        if(dfn[v = e->to]) continue;
        dfs(v, v);
    }

    return ;
}

NODE* Build(long long l, long long r){
    register NODE *p = new NODE();

    if(l ^ r){
        register long long mid = (l + r) >> 1;
        p->ls = Build(l, mid);
        p->rs = Build(mid + 1, r);
        p->sum = p->ls->sum + p->rs->sum;
    } else p->sum = val[id[l]];

    return p;
}

void update(NODE *node, long long l, long long r, long long k, long long L, long long R){
    if(l == L && r == R) node->tag += k;
    else{
        node->sum += k * (r - l + 1);
        register long long mid = (L + R) >> 1;
        if(r <= mid) update(node->ls, l, r, k, L, mid);
        else if(mid < l) update(node->rs, l, r, k, mid + 1, R);
        else {
            update(node->ls, l, mid, k, L, mid);
            update(node->rs, mid + 1, r, k, mid + 1, R);
        }
    }

    return ;
}

long long Query(NODE *node, long long l, long long r, long long L, long long R){
    if(node->tag) {
        node->sum += (R - L + 1) * node->tag;
        if(L ^ R){
            node->ls->tag += node->tag;
            node->rs->tag += node->tag;
        }
        node->tag = 0;
    }

    if(l == L && r == R) return node->sum;
    register long long mid = (L + R) >> 1;
    if(r <= mid) return Query(node->ls, l, r, L, mid);
    if(mid < l) return Query(node->rs, l, r, mid + 1, R);
    return Query(node->ls, l, mid, L, mid) + Query(node->rs, mid + 1, r, mid + 1, R);
}