BZOJ3159 决战 求调
  • 板块题目总版
  • 楼主_l_l_¯l¯l¯
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/3/9 16:05
  • 上次更新2024/3/9 18:01:38
查看原帖
BZOJ3159 决战 求调
109114
_l_l_¯l¯l¯楼主2024/3/9 16:05

题意大概是一棵树,有点权,五种操作为链加、链求和、链求 max、链求 min、链 reverse

保证第一和第五操作是直上直下的

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 50005;
namespace fhq {
	unsigned pos[MAXN]; int val[MAXN], siz[MAXN], ls[MAXN], rs[MAXN];
	bool rev[MAXN]; int add[MAXN]; long long sum[MAXN]; int minv[MAXN], maxv[MAXN];
	void addrev(int rt) {rev[rt] ^= 1; swap(ls[rt], rs[rt]);}
	void addtag(int rt, int w) {add[rt] += w; val[rt] += w; sum[rt] += 1ll * siz[rt] * w;}
	void pushdown(int rt) {
		if (rt == 0) return;
		if (rev[rt]) addrev(ls[rt]), addrev(rs[rt]), rev[rt] = 0;
		if (add[rt]) {
			if (ls[rt]) addtag(ls[rt], add[rt]); if (rs[rt]) addtag(rs[rt], add[rt]); add[rt] = 0;
		}
	}
	void pushup(int rt) {
		if (rt == 0) return;
		siz[rt] = siz[ls[rt]] + siz[rs[rt]] + 1; sum[rt] = sum[ls[rt]] + sum[rs[rt]] + val[rt];
		minv[rt] = min({minv[ls[rt]], minv[rs[rt]], val[rt]});
		maxv[rt] = max({maxv[ls[rt]], maxv[rs[rt]], val[rt]});
	}
	void split(int rt, int &x, int &y, int sz) {
		if (rt == 0) return x = y = 0, void(); pushdown(rt);
		if (siz[ls[rt]] >= sz) split(ls[rt], x, ls[y = rt], sz);
		else split(rs[rt], rs[x = rt], y, sz - siz[ls[rt]] - 1);
		pushup(x), pushup(y);
	}
	int merge(int x, int y) {
		if ((x && y) == 0) return x | y; pushdown(x); pushdown(y);
		if (pos[x] < pos[y]) return rs[x] = merge(rs[x], y), pushup(x), x;
		else return ls[y] = merge(x, ls[y]), pushup(y), y;
	}
}
vector<int> G[MAXN]; int dep[MAXN], fa[MAXN], maxs[MAXN], siz[MAXN], tp[MAXN];
void dfs1(int u, int f) {
	fa[u] = f; siz[u] = 1; dep[u] = dep[f] + 1; for (int v : G[u]) {
		if (v == f) continue; dfs1(v, u); siz[u] += siz[v];
		maxs[u] = maxs[u] && siz[maxs[u]] > siz[v] ? maxs[u] : v;
	}
}
int rt[MAXN], tmprt[MAXN];
void dfs2(int u, int t) {
	tp[u] = t; rt[t] = fhq::merge(rt[t], u); if (maxs[u]) dfs2(maxs[u], t);
	for (int v : G[u]) if (v != fa[u] && v != maxs[u]) dfs2(v, v);
}
void modify(int u, int v, int w) {
	while (tp[u] != tp[v]) {
		if (dep[tp[u]] < dep[tp[v]]) swap(u, v);
		int tmp; fhq::split(rt[tp[u]], rt[tp[u]], tmp, dep[u] - dep[tp[u]] + 1);
		fhq::addtag(rt[tp[u]], w); rt[tp[u]] = fhq::merge(rt[tp[u]], tmp); u = fa[tp[u]];
	}
	if (dep[u] < dep[v]) swap(u, v);
	int tmp; fhq::split(rt[tp[u]], tmp, rt[tp[u]], dep[v] - dep[tp[v]]);
	int tmp2; fhq::split(rt[tp[u]], rt[tp[u]], tmp2, dep[u] - dep[v] + 1);
	fhq::addtag(rt[tp[u]], w); rt[tp[u]] = fhq::merge(tmp, fhq::merge(rt[tp[u]], tmp2));
}
long long querysum(int u, int v) {
	long long ans = 0; while (tp[u] != tp[v]) {
		if (dep[tp[u]] < dep[tp[v]]) swap(u, v);
		int tmp; fhq::split(rt[tp[u]], rt[tp[u]], tmp, dep[u] - dep[tp[u]] + 1);
		ans += fhq::sum[rt[tp[u]]]; rt[tp[u]] = fhq::merge(rt[tp[u]], tmp); u = fa[tp[u]];
	}
	if (dep[u] < dep[v]) swap(u, v);
	int tmp; fhq::split(rt[tp[u]], tmp, rt[tp[u]], dep[v] - dep[tp[v]]);
	int tmp2; fhq::split(rt[tp[u]], rt[tp[u]], tmp2, dep[u] - dep[v] + 1);
	ans += fhq::sum[rt[tp[u]]]; rt[tp[u]] = fhq::merge(tmp, fhq::merge(rt[tp[u]], tmp2));
	return ans;
}
int querymax(int u, int v) {
	int ans = 0; while (tp[u] != tp[v]) {
		if (dep[tp[u]] < dep[tp[v]]) swap(u, v);
		int tmp; fhq::split(rt[tp[u]], rt[tp[u]], tmp, dep[u] - dep[tp[u]] + 1);
		ans = max(ans, fhq::maxv[rt[tp[u]]]); rt[tp[u]] = fhq::merge(rt[tp[u]], tmp); u = fa[tp[u]];
	}
	if (dep[u] < dep[v]) swap(u, v);
	int tmp; fhq::split(rt[tp[u]], tmp, rt[tp[u]], dep[v] - dep[tp[v]]);
	int tmp2; fhq::split(rt[tp[u]], rt[tp[u]], tmp2, dep[u] - dep[v] + 1);
	ans = max(ans, fhq::maxv[rt[tp[u]]]); rt[tp[u]] = fhq::merge(tmp, fhq::merge(rt[tp[u]], tmp2));
	return ans;
}
int querymin(int u, int v) {
	int ans = 0x7fffffff; while (tp[u] != tp[v]) {
		if (dep[tp[u]] < dep[tp[v]]) swap(u, v);
		int tmp; fhq::split(rt[tp[u]], rt[tp[u]], tmp, dep[u] - dep[tp[u]] + 1);
		ans = min(ans, fhq::minv[rt[tp[u]]]); rt[tp[u]] = fhq::merge(rt[tp[u]], tmp); u = fa[tp[u]];
	}
	if (dep[u] < dep[v]) swap(u, v);
	int tmp; fhq::split(rt[tp[u]], tmp, rt[tp[u]], dep[v] - dep[tp[v]]);
	int tmp2; fhq::split(rt[tp[u]], rt[tp[u]], tmp2, dep[u] - dep[v] + 1);
	ans = min(ans, fhq::minv[rt[tp[u]]]); rt[tp[u]] = fhq::merge(tmp, fhq::merge(rt[tp[u]], tmp2));
	return ans;
}
void reverse(int u, int v) {
	if (dep[u] < dep[v]) swap(u, v); int uu = u;
	int R = 0; while (tp[u] != tp[v]) {
		int tmp; fhq::split(rt[tp[u]], tmp, tmprt[tp[u]], dep[u] - dep[tp[u]] + 1);
		R = fhq::merge(tmp, R); u = fa[tp[u]];
	}
	int tmp; fhq::split(rt[tp[u]], rt[tp[u]], tmp, dep[v] - dep[tp[v]]);
	fhq::split(tmp, tmp, tmprt[tp[u]], dep[u] - dep[v] + 1); R = fhq::merge(tmp, R);
	fhq::addrev(R); u = uu; while (tp[u] != tp[v]) {
		int tmp; fhq::split(R, R, tmp, fhq::siz[R] - (dep[u] - dep[tp[u]] + 1));
		rt[tp[u]] = fhq::merge(tmp, tmprt[tp[u]]); u = fa[tp[u]];
	}
	rt[tp[u]] = fhq::merge(rt[tp[u]], fhq::merge(R, tmprt[tp[u]]));
}
mt19937 rnd(time(0));
int main() {
	fhq::minv[0] = 0x7fffffff; for (int i = 1; i < MAXN; i++) fhq::siz[i] = 1;
	int n, m, r; scanf("%d %d %d", &n, &m, &r);
	for (int i = 1; i <= n; i++) fhq::pos[i] = rnd();
	for (int i = 1; i < n; i++) {
		int u, v; scanf("%d %d", &u, &v); G[u].push_back(v); G[v].push_back(u);
	} dfs1(r, r); dfs2(r, r); while (m--) {
		char str[20]; int a, b, c; scanf("%s %d %d", str, &a, &b);
		if (str[2] == 'c') scanf("%d", &c), modify(a, b, c);
		if (str[0] == 'S') printf("%lld\n", querysum(a, b));
		if (str[1] == 'a') printf("%d\n", querymax(a, b));
		if (str[1] == 'i') printf("%d\n", querymin(a, b));
		if (str[2] == 'v') reverse(a, b);
	}
}
2024/3/9 16:05
加载中...