码迷,mamicode.com
首页 > 编程语言 > 详细

Codeforces 276E(树状数组)

时间:2015-08-21 01:54:22      阅读:216      评论:0      收藏:0      [点我收藏+]

标签:

题意:一棵树有n个节点,1是根节点,根节点的子节点是单链,然后现在有两种操作0 v x d表示距离节点v为d的节点权值都加x,操作1 v问v节点的权值,初始节点权值都是0。
题解:看了别人的题解才会的,维护两种树,把每条单链都当做一个树状数组维护当前链上每个节点的权值,另一种是从根节点开始维护距离为x的节点的权值。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define ll long long
using namespace std;
const int N = 100005;
int n, q, dis[N], root[N];//数组存深度和单链头节点
vector<int> g[N];
vector<vector<ll> > C;

int lowbit(int x) {
    return x & (-x);
}
//对于根节点的树,en代表距离根节点的长度,如果等于0就不加,因为变量sum加过了
//对于单链的树,st到en向下延伸
void Add(int st, int en, int val, int cur) {
    if (st > en)
        return;
    int sz = C[cur].size();
    for (int i = st; i < sz; i += lowbit(i))
        C[cur][i] += val;
    for (int i = en + 1; i < sz; i += lowbit(i))
        C[cur][i] -= val;
}

ll Sum(int deep, int cur) {
    ll ret = 0;
    int sz = C[cur].size();
    for (int i = deep; i > 0; i -= lowbit(i))
        ret += C[cur][i];
    return ret;
}

void dfs(int u, int pre, int cnt, int cur) {
    dis[u] = cnt;
    root[u] = cur;
    C[cur].push_back(0);
    int sz = g[u].size();
    for (int i = 0; i < sz; i++) {
        int v = g[u][i];
        if (v != pre)
            dfs(v, u, cnt + 1, cur);
    }
}

int main() {
    scanf("%d%d", &n, &q);
    for (int i = 0; i <= n; i++)
        g[i].clear();
    int a, b, op, l, r, x, v, d;
    for (int i = 1; i < n; i++) {
        scanf("%d%d", &a, &b);
        g[a].push_back(b);
        g[b].push_back(a);
    }
    int sz = g[1].size();
    C.resize(sz + 5);
    for (int i = 0; i < sz; i++) {
        C[i + 1].push_back(0);//根节点
        dfs(g[1][i], 1, 1, i + 1);
    }
    C[0].resize(N, 0);
    ll sum = 0;//根节点1的权值
    while (q--) {
        scanf("%d", &op);
        if (op == 0) {
            scanf("%d%d%d", &v, &x, &d);
            int cur = root[v];      
            if (d < dis[v])//不会延伸到其他链
                Add(dis[v] - d, dis[v] + d, x, cur);
            else {
                sum += x;
                Add(1, dis[v] + d, x, cur);//单链的子节点延伸
                Add(1, d - dis[v], x, 0);//向根节点延伸
                Add(1, d - dis[v], -x, cur);//重复加的减掉
            }
        }
        else {
            scanf("%d", &v);
            if (v == 1)
                printf("%lld\n", sum);
            else {
                int cur = root[v];
                printf("%lld\n", Sum(dis[v], cur) + Sum(dis[v], 0));//向根节点延伸的单链上的和加上根节点向下延伸的加上的权值
            }
        }
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

Codeforces 276E(树状数组)

标签:

原文地址:http://blog.csdn.net/hyczms/article/details/47821181

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!