CF383C Propagating tree

题面

题目描述

Iahub非常喜欢树木。最近,他发现了一棵有趣的树,名为传播树。该树由从 \(1\)\(N\) 编号的 \(N\) 个节点组成,每个节点 \(i\) 都有一个初始值 \(ai\) 。树的根节点为 \(1\)

该树具有一个特殊的属性:节点 \(i\) 的值增加 \(val\) 时, \(i\) 的所有子节点将会减少 \(val\) 。请注意,此时 \(i\) 的所有子节点的子节点还将增加 \(val\) ,以此类推。

本题有 \(M\) 个询问,分为两种:

1 x val 将节点 \(x\) 的值增加 \(val\)
2 x 查询节点 \(x\) 的当前值

输入格式

第一行包含两个整数 \(N,M\) ,如题目描述所说

第二行包含 \(N\) 个整数,\(a1,a2,...,an\)
接下来 \(N−1\) 行有两个整数 \(u,v\) ,代表两者之间存在一条边

接下来的\(M\)行中的每行都包含上述格式的查询

输出格式

对于每个类型为 \(2\) 的查询(查询节点 \(x\) 的值),按照输入中给出的顺序在单独的行上回答查询

输入样例

5 5
1 2 1 1 2
1 2
1 3
2 4
2 5
1 2 3
1 1 2
2 1
2 2
2 4

输出样例

3
3
0

数据范围与提示

\(1≤n,m≤200,000\)
\(1≤ai,val≤1000\)
\(1≤vi,ui\)\(x≤n\)

题解

想到线段树+dfs序。
但是由于有+和-,还是断层的。难道是bfs序??????
发现各层之间互不干扰,所以可以建两颗线段树分别维护基数层和偶数层。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 200005;
inline int read() {
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
inline void write(int x) {
	if (x < 0) {
		x = ~(x - 1);
		putchar('-');
	}
	if (x > 9)
		write(x / 10);
	putchar(x % 10 + '0');
}

int n, m;
int v[maxn];
vector <int> g[maxn];
int ll[2*maxn], rr[2*maxn], dfn[2*maxn], clk; 
int dep[maxn];
struct two_tree{
    int s[maxn * 4], a[maxn];
    int tag[4*maxn];
    void push_up(int x){
        s[x] = s[2*x] + s[2*x+1];
    }

    void push_down(int x, int len){
        tag[2*x] += tag[x];
        tag[2*x+1] += tag[x];
        s[2*x] += tag[x] * (len - len / 2);
        s[2*x+1] += tag[x] * (len / 2);
        tag[x] = 0;  
    }

    void build(int l, int r, int x){
        if(l == r){
            s[x] = a[l];
            return ;
        }
        int mid = (l+r)/2;
        build(l, mid, 2*x);
        build(mid+1, r, 2*x+1);
        push_up(x); 
    }

    void add(int dl, int dr, int l, int r, int pls, int x){
        if(l > dr or r < dl)	return ;
        if(l >= dl and r <= dr){
            s[x] += pls * (r - l + 1);
            if(l != r)	tag[x] += pls;
            return ;
        }
        int mid = (l + r) / 2;
        push_down(x, r - l + 1);
        add(dl, dr, l, mid, pls, 2*x);
        add(dl, dr, mid+1, r, pls, 2*x+1);
        push_up(x); 
    }

    int query(int dl, int dr, int l, int r, int x){
        if(l > dr or r < dl)	return 0;
        if(l >= dl and r <= dr){
            return s[x];
        }
        int mid = (l+r)/2;
        int ans = 0;
        push_down(x, r - l + 1);
        if(dl <= mid)	ans += query(dl, dr, l, mid, 2*x);
        if(dr > mid)	ans += query(dl, dr, mid+1, r, 2*x+1);
        push_up(x);
        return ans;
    }
};
two_tree A, B;


 

void dfs(int x, int fa){
    dep[x] = dep[fa] + 1;
    dfn[x] = ++clk;
    ll[x] = rr[x] = dfn[x];
    A.a[dfn[x]] = B.a[dfn[x]] = v[x];
    for(int i = 0; i < g[x].size(); i++){
        if(g[x][i] == fa)   continue;
        dfs(g[x][i], x);
        ll[x] = min(ll[x], ll[g[x][i]]);
        rr[x] = max(rr[x], rr[g[x][i]]);
    }
    return ;
}



signed main(){
    n = read(), m = read();
    for(int i = 1; i <= n; i++){
        v[i] = read();
    }
    for(int i = 1; i < n; i++){
        int u = read(), vv = read();
        // cin>>u>>vv;
        g[u].push_back(vv);
        g[vv].push_back(u);
    }
    dfs(1, 0);
    A.build(1, n, 1), B.build(1, n, 1);
    while (m--)
    {
        int op = read();
        // cin>>op;
        if(op == 2){
            int x = read();
            // cin>>x;
            if(dep[x] % 2){
                write(A.query(dfn[x], dfn[x], 1, clk, 1));
                puts("");
            }else{
                write(B.query(dfn[x], dfn[x], 1, clk, 1));
                puts("");
                // cout<<<<endl;
            }
        }else{
            int x = read(), val = read();                             
            // cin>>x>>val;
            if(dep[x] % 2){
                A.add(ll[x], rr[x], 1, clk, val, 1);
                B.add(ll[x], rr[x], 1, clk, -val, 1);
            }else{
                A.add(ll[x], rr[x], 1, clk, -val, 1);
                B.add(ll[x], rr[x], 1, clk, val, 1);
            }
            // add(ll[x], rr[x], 1, clk, 1, val);
        }
    }
//    system("PAUSE");
    return 0;
}
posted @ 2022-07-12 21:20  WRuperD  阅读(8)  评论(0编辑  收藏  举报

本文作者:DIVMonster

本文链接:https://www.cnblogs.com/guangzan/p/12886111.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

这是一条自定义内容

这是一条自定义内容