10分树剖求差错
查看原帖
10分树剖求差错
188155
K2sen楼主2020/9/8 20:58

RT

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define int long long
#define N 100010
#define M 1010

using namespace std;
const int inf = 9000000000000000000;
int n, m, root;
int dep[N], top[N], siz[N], fath[N], son[N], dfn[N], w[N], pre[N], zu[N][20];

int read() {
	int s = 0, f = 0; char ch = getchar();
	while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
	while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
	return f ? -s : s;
}

namespace Seg {
	#define lson rt << 1
	#define rson rt << 1 | 1
	struct node {
		int min, lazy;
	}tree[N << 2];
	void push_up(int rt) {
		tree[rt].min = min(tree[lson].min, tree[rson].min);
	}
	void build(int rt, int l, int r) {
		tree[rt].lazy = -1;
		if (l == r) {
			tree[rt].min = w[pre[l]];
			return;
		}
		int mid = (l + r) >> 1;
		build(lson, l, mid);
		build(rson, mid + 1, r);
		push_up(rt);
	}
	void push_down(int rt) {
		if (tree[rt].lazy == -1) return;
		tree[lson].min = tree[rson].min = tree[rt].lazy;
		tree[lson].lazy = tree[rson].lazy = tree[rt].lazy;
		tree[rt].lazy = -1;
	}
	void updata(int rt, int val, int l, int r, int L, int R) {
		if (L <= l && r <= R) {
			tree[rt].min = tree[rt].lazy = val;
			return;
		}
		push_down(rt);
		int mid = (l + r) >> 1;
		if (L <= mid) updata(lson, val, l, mid, L, R);
		if (R > mid) updata(rson, val, mid + 1, r, L, R);
		push_up(rt);
	}
	int query(int rt, int l, int r, int L, int R) {
		if (L <= l && r <= R) return tree[rt].min;
		push_down(rt);
		int mid = (l + r) >> 1, ans = inf;
		if (L <= mid) ans = min(ans, query(lson, l, mid, L, R));
		if (R > mid) ans = min(ans, query(rson, mid + 1, r, L, R));
		return ans;
	}
}

namespace Cut {
	int cnt, add_edge, head[N << 1];
	struct node {
		int next, to;
	}edge[N << 1];
	void add(int from, int to) {
		edge[++add_edge].next = head[from];
		edge[add_edge].to = to;
		head[from] = add_edge;
	}
	void dfs(int x, int fa) {
		siz[x] = 1, fath[x] = fa, dep[x] = dep[fa] + 1, zu[x][0] = fa;
		for (int i = 1; i <= 18; i++) {
			zu[x][i] = zu[zu[x][i - 1]][i - 1];
			if (!zu[x][i]) break;
		}
		for (int i = head[x]; i; i = edge[i].next) {
			int to = edge[i].to;
			if (to == fa) continue;
			dfs(to, x), siz[x] += siz[to];
			if (siz[son[x]] < siz[to]) son[x] = to;
		}
	}
	void dfs2(int x, int tp) {
		dfn[x] = ++cnt, pre[cnt] = x, top[x] = tp;
		if (son[x]) dfs2(son[x], tp);
		for (int i = head[x]; i; i = edge[i].next) {
			int to = edge[i].to;
			if (to == son[x] || to == fath[x]) continue;
			dfs2(to, to);
		}
	}
	void change(int x, int y, int val) {
		while (top[x] != top[y]) {
			if (dep[top[x]] < dep[top[y]]) swap(x, y);
			Seg::updata(1, val, 1, n, dfn[top[x]], dfn[x]);
			x = fath[top[x]];
		}
		if (dfn[x] > dfn[y]) swap(x, y);
		Seg::updata(1, val, 1, n, dfn[x], dfn[y]);
	}
	int getfa(int x, int sum) {
		for (int i = 18; i >= 0; --i)
			if (sum >= (1 << i))
				x = zu[x][i], sum -= (1 << i);
		return x;
	}
}

signed main() {
//	freopen("out.txt", "w", stdout);
	n = read(), m = read();
	for (int i = 1, x, y; i < n; i++) {
		x = read(), y = read();
		Cut::add(x, y), Cut::add(y, x);
	}
	for (int i = 1; i <= n; i++) w[i] = read();
	Cut::dfs(1, 0), Cut::dfs2(1, 1), Seg::build(1, 1, n);
	root = read();
	int sy = 0;
	for (int i = 1, opt, x, y, val; i <= m; i++) {
		opt = read();
		if (opt == 1) root = read();
		if (opt == 2) {
			x = read(), y = read(), val = read();
			Cut::change(x, y, val);
		}
		if (opt == 3) {
			x = read();
			if (x == root) printf("%lld\n", Seg::tree[1].min);
			else if (dep[x] < dep[root] && zu[y = Cut::getfa(root, dep[root] - dep[x] + 1)][0] == x) {
//				y = fath[y];
				int p = Seg::query(1, 1, n, 1, dfn[y] - 1), q;
				if (dfn[y] + siz[y] <= n) q = Seg::query(1, 1, n, dfn[y] + siz[y], n);
				else q = inf;
				printf("%lld\n", min(p, q));
			} else printf("%lld\n", Seg::query(1, 1, n, dfn[x], dfn[x] + siz[x] - 1));
		}
	}
}
/*
5 8
1 2
2 3
3 4
4 5
1 2 3 4 5
1
3 1
2 1 4 2
1 3
3 4
3 5
1 4
2 3 4 3
3 3
*/
2020/9/8 20:58
加载中...