codeforces 383C Propagating tree 线段树

http://codeforces.com/problemset/problem/383/C

题目就是说,  给一棵树,将一个节点的值+val, 那么它的子节点都会-val, 子节点的子节点+val........这样类推, 给一系列操作,2是查询一个节点的值, 1是将一个节点的值+val。

首先,<dfs一遍求出dfs序以及每个点的深度, 然后建两颗线段树, 深度为奇数的建一棵, 偶数建一棵。 改变一个节点的值, 就把与他奇偶相同的那颗树全都+val, 不同的全都-val。 具体看代码>.....

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define pb(x) push_back(x)
 4 #define ll long long
 5 #define mk(x, y) make_pair(x, y)
 6 #define lson l, m, rt<<1
 7 #define mem(a) memset(a, 0, sizeof(a))
 8 #define rson m+1, r, rt<<1|1
 9 #define mem1(a) memset(a, -1, sizeof(a))
10 #define mem2(a) memset(a, 0x3f, sizeof(a))
11 #define rep(i, a, n) for(int i = a; i<n; i++)
12 #define ull unsigned long long
13 typedef pair<int, int> pll;
14 const double PI = acos(-1.0);
15 const double eps = 1e-8;
16 const int mod = 1e9+7;
17 const int inf = 1061109567;
18 const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
19 const int maxn = 2e5+5;
20 int in[maxn], out[maxn], num, val[maxn], head[maxn], dis[maxn], dfs_clock;
21 int cnt[maxn<<2][2];
22 struct node
23 {
24     int to, nextt;
25 }e[maxn*2];
26 void add(int u, int v) {
27     e[num].to = v;
28     e[num].nextt = head[u];
29     head[u] = num++;
30 }
31 void dfs(int u, int fa) {
32     dis[u] = dis[fa]+1;
33     in[u] = ++dfs_clock;
34     for(int i = head[u]; ~i; i = e[i].nextt) {
35         int v = e[i].to;
36         if(v == fa)
37             continue;
38         dfs(v, u);
39     }
40     out[u] = dfs_clock;
41 }
42 void pushDown(int rt, int sign) {
43     if(cnt[rt][sign]) {
44         cnt[rt<<1][sign] += cnt[rt][sign];
45         cnt[rt<<1|1][sign] += cnt[rt][sign];
46         cnt[rt][sign] = 0;
47     }
48 }
49 void update(int L, int R, int l, int r, int rt, int val, int sign) {
50     if(L<=l && R>=r) {
51         cnt[rt][sign] += val;
52         return ;
53     }
54     pushDown(rt, sign);
55     int m = l+r>>1;
56     if(L<=m)
57         update(L, R, lson, val, sign);
58     if(R>m)
59         update(L, R, rson, val, sign);
60 }
61 int query(int p, int l, int r, int rt, int sign) {
62     if(l == r) {
63         return cnt[rt][sign];
64     }
65     pushDown(rt, sign);
66     int m = l+r>>1;
67     int ret = 0;
68     if(p<=m)
69         return query(p, lson, sign);
70     else
71         return query(p, rson, sign);
72 }
73 int main()
74 {
75     int n, m, x, y, z;
76     cin>>n>>m;
77     for(int i = 1; i<=n; i++) {
78         scanf("%d", &val[i]);
79     }
80     mem1(head);
81     for(int i = 0; i<n-1; i++) {
82         scanf("%d%d", &x, &y);
83         add(x, y);
84         add(y, x);
85     }
86     dis[0] = 0;
87     dfs(1, 0);
88     while(m--) {
89         scanf("%d", &z);
90         if(z == 2) {
91             scanf("%d", &x);
92             printf("%d\n", query(in[x], 1, n, 1, dis[x]&1)+val[x]);
93         } else {
94             scanf("%d%d", &x, &y);
95             update(in[x], out[x], 1, n, 1, y, dis[x]&1);
96             update(in[x], out[x], 1, n, 1, -y, !(dis[x]&1));
97         }
98     }
99 }

 

转载于:https://www.cnblogs.com/yohaha/p/5009462.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值