换根树剖板子题求助
查看原帖
换根树剖板子题求助
178519
tidongCrazy楼主2020/11/30 18:46

rt,样例都过不去

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

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

const int N = 1e6 + 5;

int head[N], cnt = 0;
struct edge { int v, nex; } e[N];
inline void add_edge(int u, int v) {
	
	e[++ cnt].v = v; e[cnt].nex = head[u]; head[u] = cnt;
	e[++ cnt].v = u; e[cnt].nex = head[v]; head[v] = cnt;
}

int n, Q, arr[N], son[N], top[N], siz[N], fa[N], dep[N], w1[N], w2[N], id[N], tot = 0;
struct SegMent { int l, r, lc, rc, ans, tag; } tr[N];

inline void dfs1(int x, int f, int dept) {
	
	fa[x] = f; dep[x] = dept; siz[x] = 1;
	for(int i = head[x]; i; i = e[i].nex) {
		int v = e[i].v;
		if(v == f) continue;
		dfs1(v, x, dept + 1);
		siz[x] += siz[v];
		if(siz[v] > siz[son[x]]) son[x] = v;
	}
} inline void dfs2(int x, int topf) {
	
	top[x] = topf; id[x] = ++ tot; w2[tot] = w1[x];
	if(!son[x]) return;
	dfs2(son[x], topf);
	for(int i = head[x]; i; i = e[i].nex) {
		int v = e[i].v;
		if(v == fa[x] || v == son[x]) continue;
		dfs2(v, v);
	}
}

#define mid ((tr[x].l + tr[x].r) >> 1)

inline void pushup(int x) { tr[x].ans = tr[tr[x].lc].ans + tr[tr[x].rc].ans; }

inline int build(int x, int l, int r) {
	
	tr[x].l = l; tr[x].r = r; tr[x].tag = 0;
	if(l == r) { tr[x].ans = w2[l]; return x; }
	tr[x].lc = build(x << 1, l, mid);
	tr[x].rc = build(x << 1 | 1, mid + 1, r);
	pushup(x); return x;
}

inline void pushdown(int x) {
	
	if(tr[x].tag) {
		tr[tr[x].lc].tag += tr[x].tag;
		tr[tr[x].rc].tag += tr[x].tag;
		tr[tr[x].lc].ans += (tr[tr[x].lc].r - tr[tr[x].lc].l + 1) * tr[x].tag;
		tr[tr[x].rc].ans += (tr[tr[x].rc].r - tr[tr[x].rc].l + 1) * tr[x].tag;
		tr[x].tag = 0;
	}
}

inline void modify(int x, int nl, int nr, int c) {
	
	if(nl <= tr[x].l && tr[x].r <= nr) {
		tr[x].tag += c;
		tr[x].ans += (tr[x].r - tr[x].l + 1) * c;
		return;
	} pushdown(x);
	if(nl <= mid) modify(tr[x].lc, nl, nr, c);
	if(nr > mid) modify(tr[x].rc, nl, nr, c);
	pushup(x);
}

inline int query(int x, int nl, int nr) {
	
	if(nl <= tr[x].l && tr[x].r <= nr) return tr[x].ans;
	pushdown(x); int res = 0;
	if(nl <= mid) res += query(tr[x].lc, nl, nr);
	if(nr > mid) res += query(tr[x].rc, nl, nr);
	return res;
}

inline int P(int x, int y) {
	
	while(top[x] != top[y]) {
		if(dep[top[x]] <dep[top[y]]) swap(x, y);
		if(fa[top[x]] == y) return top[x];
		x = fa[top[x]];
	} if(dep[x] > dep[y]) swap(x, y);
	return son[x];
}

inline int LCA(int x, int y) {
	
	while(top[x] != top[y]) {
		if(dep[top[x]] < dep[top[y]]) swap(x, y);
		x = fa[top[x]];
	} return dep[x] < dep[y] ? x : y;
}

int rt = 1;

inline int Query(int x) {
	
	if(x == rt) return query(1, 1, n);
	int lca = LCA(x, rt);
	if(lca == rt) return query(1, id[x], id[x] + siz[x] - 1);
	if(lca != x) return query(1, id[x], id[x] + siz[x] - 1);
	int p = P(x, rt);
	return query(1, 1, n) - query(1, id[p], id[p] + siz[p] - 1);
}

inline void Change(int x, int c) {
	
	if(x == rt) { modify(1, 1, n, c); return; }
	int lca = LCA(x, rt);
	if(lca == rt) { modify(1, id[x], id[x] + siz[x] - 1, c); return; }
	if(lca != x) { modify(1, id[x], id[x] + siz[x] - 1, c); return; }
	modify(1, 1, n, c);
	int p = P(x, rt);
	modify(1, id[p], id[p] + siz[p] - 1, -c);
}

int main() {
	
	n = read(); Q = read();
	for(int i = 1; i <= n; i ++ ) w1[i] = read();
	for(int i = 1; i < n; i ++ ) {
		int u = read(), v = read();
		add_edge(u, v);
	} dfs1(1, 0, 1); dfs2(1, 1); build(1, 1, n);
	while(Q -- ) {
		int opt = read();
		if(opt == 1) {
			int x = read();
			rt = x;
		} if(opt == 2) {
			int x = read(), y = read(), v = read();
			int lca = LCA(x, y);
			Change(lca, v);
		} if(opt == 3) {
			int x = read();
			printf("%d\n", Query(x));
		}
	}
}
2020/11/30 18:46
加载中...