题意:给出一颗树,每次对树进行两种操作,第一种操作:给节点v及距离节点v,d个单位长度以内的节点加x 第二种操作:询问节点v当前的值。
注意:给出的树中,除了节点1以为,其他节点的度都不会超过2。
思路:刚开始逗比没看到上面那个条件,有了上面这个条件后可以发现,这种树肯定是节点1拖着很多直链的。看到别人的做法几乎都是开n颗线段树的,而我是用两颗线段树做的。首先,求出所有节点的深度(根节点深度为1),并给每个节点编个号。然后再建两颗线段树,一颗是维护深度的线段树(代表深度为i的节点都加x),一颗是维护一条链的所有节点。第一种操作的时候,如果节点v加上d之后不能到达节点1,则只对单条链进行操作;如果能到达节点1,则说明深度为[1, d - depth[v]]的节点都能到达,给这些深度统一加上x,也就相当于区间加一个值,然后剩下一条链,然后再维护这条链。
我的做法需要注意的细节有点多,都在if里面= =!
#include
#include
#include
#include
#define pb push_back
using namespace std;
const int N = 100005;
int n, nq, stamp;
int depth[N], id[N], size[N];
vector vec[N];
struct SegTree {
int tree[N << 2], add[N << 2];
void pushDown(int i, int l, int r) {
if(add != 0) {
tree[i << 1] += add[i] * l;
tree[i << 1 | 1] += add[i] * r;
add[i << 1] += add[i];
add[i << 1 | 1] += add[i];
add[i] = 0;
}
}
void update(int l, int r, int i, int ql, int qr, int val) {
if(l > qr || ql > r || ql > qr)
return ;
if(l >= ql && r <= qr) {
tree[i] += val * (r - l + 1);
add[i] += val;
return ;
}
int mid = l + r >> 1;
pushDown(i, mid - l + 1, r - mid);
update(l, mid, i << 1, ql, qr, val);
update(mid + 1, r, i << 1 | 1, ql, qr, val);
tree[i] = tree[i << 1] + tree[i << 1 | 1];
}
int query(int l, int r, int i, int loc) {
if(l > loc || loc > r)
return 0;
if(l == r)
return tree[i];
int mid = l + r >> 1;
pushDown(i, mid - l + 1, r - mid);
return query(l, mid, i << 1, loc)
+ query(mid + 1, r, i << 1 | 1, loc);
}
} all, chain;
void dfs(int u, int fa) {
id[u] = ++stamp;
for(int i = 0; i < (int)vec[u].size(); i++) {
int e = vec[u][i];
if(e == fa)
continue;
depth[e] = depth[u] + 1;
dfs(e, u);
size[u] = size[e] + 1;
}
}
int main() {
cin >> n >> nq;
for(int i = 0; i < n - 1; i++) {
int a, b;
scanf("%d%d", &a, &b);
vec[a].pb(b), vec[b].pb(a);
}
dfs(1, -1);
while(nq--) {
int ord, v, x, d;
scanf("%d", &ord);
if(ord == 0) {
scanf("%d%d%d", &v, &x, &d);
int length = d - depth[v];
if(length > 0) {
int l, r;
all.update(1, N - 1, 1, 1, length + 1, x);
if(d > size[v]) {
r = id[v] + size[v];
} else {
r = id[v] + d;
}
if(v != 1) {
l = id[v] + length - depth[v] + 1;
chain.update(1, N - 1, 1, l, r, x);
}
} else {
int l = id[v] - d, r;
if(d > size[v]) {
r = id[v] + size[v];
} else {
r = id[v] + d;
}
if(v != 1) {
if(depth[v] - d == 0) {
chain.update(1, N - 1, 1, l + 1, r, x);
chain.update(1, N - 1, 1, 1, 1, x);
} else {
chain.update(1, N - 1, 1, l, r, x);
}
}
}
} else {
scanf("%d", &v);
int ans = all.query(1, N - 1, 1, depth[v] + 1)
+ chain.query(1, N - 1, 1, id[v]);
printf("%d\n", ans);
}
}
return 0;
}