# BZOJ4372: 烁烁的游戏【动态点分治】

## Description

Q x：询问x的点权。
M x d w：将树上与节点x距离不超过d的节点的点权均加上w。

7 6
1 2
1 4
1 5
2 3
2 7
5 6
M 1 1 2
Q 5
M 2 2 3
Q 3
M 1 2 1
Q 2

2
3
6

## HINT

$n，m<=10^5,|w|<=10^4$

## 思路

#include<bits/stdc++.h>

using namespace std;

int res = 0, w = 1; char c = getchar();
while (!isdigit(c) && c != '-') c = getchar();
if (c == '-') w = -1, c = getchar();
while (isdigit(c)) res = (res << 1) + (res << 3) + c - '0', c = getchar();
return res * w;
}

const int N = 1e5 + 10;
const int LOG = 20;

struct Edge {
int v, nxt;
Edge(int v = 0, int nxt = 0): v(v), nxt(nxt) {}
} E[N << 1];
int n, q;
char c[10];

void addedge(int u, int v) {
}

namespace LCA {

struct Node {
int id, depth;
Node(int id = 0, int depth = 0): id(id), depth(depth) {}
bool operator < (const Node b) const {
return depth < b.depth;
}
} ST[N << 1][LOG];
int first[N], dep[N], log[N << 1], len;

void dfs(int u, int fa) {
dep[u] = dep[fa] + 1;
ST[++len][0] = Node(u, dep[u]);
first[u] = len;
for (int i = head[u]; i; i = E[i].nxt) {
int v = E[i].v;
if (v == fa) continue;
dfs(v, u);
ST[++len][0] = Node(u, dep[u]);
}
}

void init() {
dfs(1, 0);
log[1] = 0;
for (int i = 2; i <= len; i++) log[i] = log[i >> 1] + 1;
for (int j = 1; (1 << j) <= len; j++) {
for (int i = 1; i + (1 << j) - 1 <= len; i++) {
ST[i][j] = min(ST[i][j - 1], ST[i + (1 << (j - 1))][j - 1]);
}
}
}

int getdis(int u, int v) {
if (first[u] < first[v]) swap(u, v);
int k = log[first[u] - first[v] + 1];
int lca = min(ST[first[v]][k], ST[first[u] - (1 << k) + 1][k]).id;
return dep[u] + dep[v] - (dep[lca] << 1);
}

}

namespace Tree_Devide {

int father[N], dep[N], maxdep;
int siz[N], F[N], siz_all, rt;
bool vis[N];
vector<int> bit[2][N];

void modify(int x, int vl, int typ, int u) {
int len = bit[typ][u].size();
while (x < len) {
bit[typ][u][x] += vl;
x += x & (-x);
}
}

void modify(int l, int r, int vl, int typ, int u) {
modify(l + 1, vl, typ, u);
modify(r + 2, -vl, typ, u);
}

int query(int x, int typ, int u) {
int len = bit[typ][u].size(), res = 0;
x = min(x + 1, len - 1);
while (x) {
res += bit[typ][u][x];
x -= x & (-x);
}
return res;
}

void getsiz(int u, int fa) {
siz[u] = 1;
for (int i = head[u]; i; i = E[i].nxt) {
int v = E[i].v;
if (v == fa || vis[v]) continue;
dep[v] = dep[u] + 1;
maxdep = max(maxdep, dep[v]);
getsiz(v, u);
siz[u] += siz[v];
}
}

void getroot(int u, int fa) {
F[u] = 0;
dep[u] = dep[fa] + 1;
maxdep = max(maxdep, dep[u]);
for (int i = head[u]; i; i = E[i].nxt) {
int v = E[i].v;
if (v == fa || vis[v]) continue;
getroot(v, u);
F[u] = max(F[u], siz[v]);
}
F[u] = max(F[u], siz_all - siz[u]);
if (F[u] < F[rt]) rt = u;
}

void solve(int u, int fa) {
father[u] = fa;
vis[u] = 1;
maxdep = dep[u] = 0;
getsiz(u, 0);
bit[0][u].resize(maxdep + 4);
for (int i = head[u]; i; i = E[i].nxt) {
int v = E[i].v;
if (vis[v]) continue;
F[rt = 0] = siz_all = siz[v];
maxdep = 0;
getroot(v, 0);
bit[1][rt].resize(maxdep + 4);
solve(rt, u);
}
}

void init() {
getsiz(1, 0);
F[rt = 0] = siz_all = n;
getroot(1, 0);
solve(rt, 0);
}

void modify_tree(int u, int k, int num) {
modify(0, k, num, 0, u);
for (int cur = u; father[cur]; cur = father[cur]) {
int dis = LCA::getdis(u, father[cur]);
if (k >= dis) {
modify(0, k - dis, num, 0, father[cur]);
modify(0, k - dis, num, 1, cur);
}
}
}

int query_tree(int u) {
int res = query(0, 0, u);
for (int cur = u; father[cur]; cur = father[cur]) {
int dis = LCA::getdis(u, father[cur]);
res += query(dis, 0, father[cur]);
res -= query(dis, 1, cur);
}
return res;
}

}

int main() {
#ifdef dream_maker
freopen("input.txt", "r", stdin);
#endif
for (int i = 1; i < n; i++) {
}
LCA::init();
Tree_Devide::init();
while (q--) {
scanf("%s", c);
if (c[0] == 'M') {