Vasya and a Tree CodeForces - 1076E(线段树+dfs)
I - Vasya and a Tree
其实参考完别人的思路,写完程序交上去,还是没理解啥意思。。昨晚再仔细想了想。终于弄明白了(有可能不对
题意是有一棵树n个点,初始时候每个点权值都为0,m次修改,对v的叶子节点且距离小于d的都加上x
也就是v以下d层包括v自身都加上x 问最后每个点的权值
现在一想 用线段树来维护就是很自然的事了
但是要维护什么值呢
维护的就是某个深度上增加的值
先更新 后回溯取消更新
详见代码注释
#include <cstdio> #include <vector> #include <algorithm> #include <cstring> #define lp p<<1 #define rp p<<1|1 #define ll long long using namespace std; const int maxn = 3e5 + 10; typedef pair<int, int> P; int n, m; int tot, head[maxn]; struct Edge{ int to, next; }edge[maxn<<1]; vector<P> vec[maxn]; ll a[maxn<<2], lazy[maxn<<2], res[maxn]; inline void addedge(int u, int v) { edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } inline void pushup(int p) { a[p] = a[lp] + a[rp]; } inline void pushdown(int p, int llen, int rlen) { if (lazy[p]) { lazy[lp] += lazy[p]; lazy[rp] += lazy[p]; a[lp] += lazy[p] * llen; a[rp] += lazy[p] * rlen; lazy[p] = 0; } } void build(int p, int l, int r) { a[p] = lazy[p] = 0; if (l == r) return; int mid = l + r >> 1; build(lp, l, mid); build(rp, mid + 1, r); pushup(p); } void update(int p, int l, int r, int x, int y, int z) { if (x <= l && y >= r) { a[p] += 1LL * z * (r - l + 1); lazy[p] += z; return; } int mid = l + r >> 1; pushdown(p, mid - l + 1, r - mid); if (x <= mid) update(lp, l, mid, x, y, z); if (y > mid) update(rp, mid + 1, r, x, y, z); pushup(p); } ll query(int p, int l, int r, int u) { if (l == r) return a[p]; int mid = l + r >> 1; pushdown(p, mid - l + 1, r - mid); if (u <= mid) return query(lp, l, mid, u); return query(rp, mid + 1, r, u); } //截至这里 应该都是线段树的基本操作 没啥好说的 void dfs(int f, int u, int d) { for (int i = 0, sz = vec[u].size(); i < sz; i++) { // 因为线段树记录的是深度 所以就可以把当前结点以及深度差为k的全部更新一遍 update(1, 1, n, d, min(n, d + vec[u][i].first), vec[u][i].second); } //接下来dfs遍历的时候的update操作不会影响到父节点了 所以可以直接query得到答案 res[u] = query(1, 1, n, d); for (int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if (v == f) continue; // 深度位置是共享的 比如 1既连接2又连接3 上面更新了深度为1,2的 在线段树上 2代表的就是2和3的权值 dfs(u, v, d + 1); } for (int i = 0; i < vec[u].size(); i++) { //回溯取消标记 update(1, 1, n, 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, u, v; i < n - 1; i++) { scanf("%d%d", &u, &v); addedge(u, v); addedge(v, u); } scanf("%d", &m); while (m--) { 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) puts(""); else putchar(' '); } return 0; }

浙公网安备 33010602011771号