Codeforces 1076E——回溯

版权声明:欢迎大家转载,转载请注明出处 https://blog.csdn.net/hao_zong_yin/article/details/84103103

题意:给出一棵以1为根的有根树,边权全部为1,点权初始全部为0,给出m个查询,每个查询给出三个变量v d x,表示将v节点的子节点(包括自己)中与v之间的距离<=d的节点的点权增加x,问最后每个节点的点权是多少

1<=n<=3e5, 1<=m<=3e5,1<=v<=n, 1<=d, x<=1e9

思路:开一棵线段树表示某个深度上增加的值,这样在dfs到一个节点时,首先将它身上的查询更新一下,回溯时再将之前的更新取消就可以了

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 10;
typedef long long ll;
typedef pair<int, int> P;
int n, m;
int tot, head[maxn];
struct Edge { int to, next; }edges[maxn<<1];
vector<P> vec[maxn];
ll a[maxn<<2], lazy[maxn<<2], res[maxn];

void addedge(int u, int v) {
    edges[tot].to = v; edges[tot].next = head[u]; head[u] = tot++;
}
void pushup(int root) {
    a[root] = a[root<<1] + a[root<<1|1];
}
void pushdown(int root, int lenl, int lenr) {
    if (lazy[root] == 0) return;
    lazy[root<<1] += lazy[root];
    lazy[root<<1|1] += lazy[root];
    a[root<<1] += lazy[root]*lenl;
    a[root<<1|1] += lazy[root]*lenr;
    lazy[root] = 0;
}
void build(int l, int r, int root) {
    a[root] = lazy[root] = 0;
    if (l == r) return;
    int mid = (l + r)>>1;
    build(l, mid, root<<1);
    build(mid+1, r, root<<1|1);
    pushup(root);
}
void update(int l, int r, int root, int ul, int ur, int v) {
    if (ul <= l && r <= ur) {
        a[root] += v;
        lazy[root] += v;
        return;
    }
    int mid = (l + r)>>1;
    pushdown(root, mid-l+1, r-mid);
    if (ul <= mid) update(l, mid, root<<1, ul, ur, v);
    if (mid < ur) update(mid+1, r, root<<1|1, ul, ur, v);
    pushup(root);
}
ll query(int l, int r, int root, int p) {
    if (l == r) return a[root];
    int mid = (l + r)>>1;
    pushdown(root, mid-l+1, r-mid);
    if (p <= mid) return query(l, mid, root<<1, p);
    else return query(mid+1, r, root<<1|1, p);
}
void dfs(int f, int u, int d) {
    for (int i = 0; i < vec[u].size(); i++) {
        update(1, n, 1, d, min(n, d+vec[u][i].first), vec[u][i].second);
    }
    res[u] = query(1, n, 1, d);
    for (int i = head[u]; ~i; i = edges[i].next) {
        int v = edges[i].to;
        if (v == f) continue;
        dfs(u, v, d+1);
    }
    for (int i = 0; i < vec[u].size(); i++) {
        update(1, n, 1, d, min(n, d+vec[u][i].first), -vec[u][i].second);
    }
}

int main() {
    scanf("%d", &n);
    tot = 0;
    memset(head, -1, sizeof(head));
    for (int i = 0; i < n-1; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        addedge(u, v);
        addedge(v, u);
    }
    scanf("%d", &m);
    for (int i = 0; i <= n; i++) vec[i].clear();
    for (int i = 0; i < m; i++) {
        int v, d, x;
        scanf("%d %d %d", &v, &d, &x);
        vec[v].push_back(make_pair(d, x));
    }
    dfs(-1, 1, 1);
    for (int i = 1; i <= n; i++) {
        printf("%I64d", res[i]);
        if (i == n) printf("\n");
        else printf(" ");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hao_zong_yin/article/details/84103103
今日推荐