DFS序1

给一棵有根树,这棵树由编号为1..N的N个结点组成。根结点的编号为R。
每个结点都有一个权值,结点i的权值为vi 。
接下来有M组操作,操作分为两类:
1 a x,表示将结点a的权值增加x;
2 a,表示求结点a的子树上所有结点的权值之和。
输入格式
第一行有三个整数N,M和R。
第二行有N个整数,第i个整数表示vi 。
在接下来的N-1行中,每行两个整数,表示一条边。
在接下来的M行中,每行一组操作。
输出格式
对于每组2 a操作,输出一个整数,表示「以结点a为根的子树」上所有结点的权值之和。
样例
样例输入 1
10 14 9
12 -6 -4 -3 12 8 9 6 6 2
8 2
2 10
8 6
2 7
7 1
6 3
10 9
2 4
10 5
1 4 -1
2 2
1 7 -1
2 10
1 10 5
2 1
1 7 -5
2 5
1 1 8
2 7
1 8 8
2 2
1 5 5
2 6
样例输出 1

21
34
12
12
23
31
4
1<=N,M<=10^6,1<=R<=N
-10^6<=vi,x<=10^6

 

Sol:

使用BIT单点修改,区间查询。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 6;
typedef long long ll;
ll c[maxn], in[maxn], out[maxn], tot, d[maxn], head[maxn], cnt, n, m, r;
struct node {
    int to, nxt;
} e[maxn << 1];
void addedge(int u, int v) {
    e[++tot] = { v, head[u] };
    head[u] = tot;
}
void dfs(int u) {
    in[u] = ++cnt;
    for (int i = head[u]; i; i = e[i].nxt) {
        int v = e[i].to;
        if (in[v])
            continue;
        dfs(v);
    }
    out[u] = cnt;
}
ll lowbit(int x) 
{ 
	return x & -x; 
}
void add(int u, int x) 
{
    while (u <= n) 
	{
        c[u] += x;
        u += lowbit(u);
    }
}
ll query(int u) {
    ll ret = 0;
    while (u > 0) {
        ret += c[u];
        u -= lowbit(u);
    }
    return ret;
}
int main() {
    cin >> n >> m >> r;
    for (int i = 1; i <= n; ++i) cin >> d[i];
    for (int i = 1, a, b; i < n; ++i) 
	{
        cin >> a >> b;
        addedge(a, b), addedge(b, a);
    }
    dfs(r);
    for (int i = 1; i <= n; ++i) //最始权值 
	    add(in[i], d[i]);
    for (int i = 1, op, a, x; i <= m; ++i) 
	{
        cin >> op >> a;
        if (op == 2) 
		{
            cout << query(out[a]) - query(in[a] - 1) << endl;
        } 
		else 
		{
            cin >> x;
            add(in[a], x);
        }
    }
}

  

posted @ 2019-11-04 21:38  我微笑不代表我快乐  阅读(289)  评论(0编辑  收藏  举报