# [BZOJ3730][震波][动态树分治+线段树+LCA]

#### 题目大意：

(0,x,k)$(0,x,k)$ 求所有和节点x距离不超过K的节点权值和
(1,x,y)$(1,x,y)$ 将节点x的权值修改为y

#### 代码：

4KB+的代码调试起来真的爽~


#include <cstdio>
const int Maxn = 500100;
inline void swap(int &x, int &y) {
static int tmp;
tmp = x;
x = y;
y = tmp;
}
inline int Max(const int &a, const int &b) {
return a > b ? a : b;
}
inline char get(void) {
static char buf[1000000], *p1 = buf, *p2 = buf;
if (p1 == p2) {
p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin);
if (p1 == p2) return EOF;
}
return *p1++;
}
x = 0; static char c; bool minus = false;
for (; !(c >= '0' && c <= '9'); c = get()) if (c == '-') minus = true;
for (; c >= '0' && c <= '9'; x = x * 10 + c - '0', c = get()); if (minus) x = -x;
}
inline void write(int x) {
if (!x) return (void) puts("0");
if (x < 0) putchar('-'), x = -x;
static short s[12], t;
while (x) s[++t] = x % 10, x /= 10;
while (t) putchar('0' + s[t--]);
putchar('\n');
}
int n, m, ans;
struct Edge {
int to, nxt;
Edge (void) {}
Edge (const int &to, const int &nxt) : to(to), nxt(nxt) {}
} edge[Maxn << 1];

inline void add(int a, int b) {
}
int dep[Maxn], ff[Maxn][25];
inline void dfs1(int u, int fa) {
ff[u][0] = fa;
for (int i = 1; i <= 20; i++) {
ff[u][i] = ff[ff[u][i - 1]][i - 1];
}
for (int i = head[u], v; i; i = edge[i].nxt) {
v = edge[i].to;
if (v == fa) continue;
dep[v] = dep[u] + 1;
dfs1(v, u);
}
}
inline int lca(int x, int y) {
if (dep[x] < dep[y]) swap(x, y);
int tmp = dep[x] - dep[y];
for (int k = 0, j = 1; j <= tmp; j <<= 1, k++)
if (tmp & j) x = ff[x][k];
while (x != y) {
int j = 0;
while (ff[x][j] != ff[y][j]) j++;
if (j) j--;
x = ff[x][j], y = ff[y][j];
}
return x;
}
inline int dist(int x, int y) {
return dep[x] + dep[y] - (dep[lca(x, y)] << 1);
}
int s[Maxn << 4], sz, ls[Maxn << 4], rs[Maxn << 4], root[Maxn][2];
inline void insert(int &k, int l, int r, int v, int p) {
if (!k) k = ++sz; s[k] += p;
if (l == r) return;
int mid = (l + r) >> 1;
if (mid >= v) insert(ls[k], l, mid, v, p);
else insert(rs[k], mid + 1, r, v, p);
}
inline int query(int k, int l, int r, int L, int R) {
if (!k) return 0;
if (l >= L && r <= R) return s[k];
int mid = (l + r) >> 1;
if (R <= mid) return query(ls[k], l, mid, L, R);
else if (L > mid) return query(rs[k], mid + 1, r, L, R);
else return query(ls[k], l, mid, L, mid) + query(rs[k], mid + 1, r, mid + 1, R);
}
bool vis[Maxn];
int d[Maxn], v[Maxn], size, son[Maxn], rnt, mson[Maxn], p[Maxn];
inline void run(int rt, int l, int u, int fa) {
insert(root[rt][l], 0, n, d[u], v[u]);
for (int i = head[u], v; i; i = edge[i].nxt) {
v = edge[i].to;
if (v == fa || vis[v]) continue;
d[v] = d[u] + 1;
run(rt, l, v, u);
}
}
inline void getroot(int u, int fa) {
son[u] = 1; mson[u] = 0;
for (int i = head[u], v; i; i = edge[i].nxt) {
v = edge[i].to;
if (v == fa || vis[v]) continue;
getroot(v, u);
son[u] += son[v];
mson[u] = Max(mson[u], son[v]);
}
mson[u] = Max(mson[u], size - son[u]);
if (mson[u] < mson[rnt]) rnt = u;
}
inline void work(int u) {
vis[u] = 1; d[u] = 0; run(u, 0, u, 0);
for (int i = head[u], v; i; i = edge[i].nxt) {
v = edge[i].to;
if (vis[v]) continue;
size = son[v]; rnt = 0;
d[v] = 1;
getroot(v, 0); run(rnt, 1, v, u);
p[rnt] = u;
work(rnt);
}
}
inline int ask(int u, int k) {
int ret = query(root[u][0], 0, n, 0, k);
for (int i = u; p[i]; i = p[i]) {
int cn = dist(u, p[i]);
ret += query(root[p[i]][0], 0, n, 0, k - cn);
ret -= query(root[i][1], 0, n, 0, k - cn);
}
return ret;
}
inline void update(int u, int k) {
int sub = k - query(root[u][0], 0, n, 0, 0);
insert(root[u][0], 0, n, 0, sub);
for (int i = u; p[i]; i = p[i]) {
int cn = dist(u, p[i]);
insert(root[p[i]][0], 0, n, cn, sub);
insert(root[i][1], 0, n, cn, sub);
}
}
int main(void) {
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
for (int i = 1; i <= n; i++) read(v[i]);
for (int i = 1, u, v; i < n; i++) {
}
size = mson[0] = n;
dfs1(1, 0);
getroot(1, 0);
work(rnt);

for (int i = 1, op, x, y; i <= m; i++) {
}