树链剖分 题型总结二

P1505 [国家集训队]旅游

https://www.luogu.org/problem/P1505
这道题 是边剖
我们要注意的是 我们的一条边上路权 可以分配给这条树下 深度较深的 节点上 边权转点权就好
而且 更要注意的是 我们的LCA 这个点的权不应该算入 因为他算上了 他父亲到他的路 所以这时候 idx[x] + 1 跳过就好

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
const int INF = 0x3f3f3f3f;
int n, k, m;
int head[maxn], sonw[maxn], cnt;
int to[maxn << 1], nxt[maxn << 1], val[maxn << 1];
pair<int, int> e[maxn];
void ade(int a, int b, int c) {
	to[++ cnt] = b, val[cnt] = c;
	nxt[cnt] = head[a], head[a] = cnt;
}

int fa[maxn], dep[maxn], siz[maxn], son[maxn];
void dfs1(int u, int f) {
	fa[u] = f;
	dep[u] = dep[f] + 1;
	siz[u] = 1;
	int maxsize = -1;
	for(int i = head[u]; i; i = nxt[i]) {
		int v = to[i];
		if(v == f) continue;
		sonw[v] = val[i];
		dfs1(v, u);
		siz[u] += siz[v];
		if(siz[v] > maxsize) {
			maxsize = siz[v];
			son[u] = v;
		}
	}
}

int tim, dfn[maxn], top[maxn], w[maxn];
void dfs2(int u, int t) {
	dfn[u] = ++ tim;
	top[u] = t;
	w[tim] = sonw[u];
	if(!son[u]) return;
	dfs2(son[u], t);
	for(int i = head[u]; i; i = nxt[i]) {
		int v = to[i];
		if(v == fa[u] || v == son[u]) continue;
		dfs2(v, v);
	}
}

int tree[maxn << 2], lazy[maxn << 2], mi[maxn << 2], ma[maxn << 2];
void push_up(int rt) {
	tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
	ma[rt] = max(ma[rt << 1], ma[rt << 1 | 1]);
	mi[rt] = min(mi[rt << 1], mi[rt << 1 | 1]);
}
void push_down(int rt) {
	if(!lazy[rt]) return ;
	tree[rt << 1] = -tree[rt << 1], lazy[rt << 1] ^= 1;
	tree[rt << 1 | 1] = -tree[rt << 1 | 1] ,lazy[rt << 1 | 1] ^= 1;
	int t1 = ma[rt << 1], t2 = ma[rt << 1 | 1];
	int s1 = mi[rt << 1], s2 = mi[rt << 1 | 1];
	ma[rt << 1] = -s1, ma[rt << 1 | 1] = -s2;
	mi[rt << 1] = -t1, mi[rt << 1 | 1] = -t2;
	lazy[rt] = 0;
}

void build(int l, int r, int rt) {
	if(l == r) {
		tree[rt] = mi[rt] = ma[rt] = w[l];
		return ;
	}
	int mid = l + r >> 1;
	build(l, mid, rt << 1);
	build(mid + 1, r, rt << 1 | 1);
	push_up(rt);
}

void updata(int L, int R, int l, int r, int rt) {
	if(L <= l && r <= R) {
		tree[rt] = -tree[rt], lazy[rt] ^= 1;
		int t = ma[rt], s = mi[rt];
		ma[rt] = -s, mi[rt] = -t;
		return ;
	}
	int mid = l + r >> 1;
	push_down(rt);
	if(L <= mid) updata(L, R, l, mid, rt << 1);
	if(R > mid) updata(L, R, mid + 1, r, rt << 1 | 1);
	push_up(rt);
}

void upd(int L, int l, int r, int rt, int val) {
	if(l == r) {
		tree[rt] = mi[rt] = ma[rt] = val;
		return ;
	}
	int mid = l + r >> 1;
	push_down(rt);
	if(L <= mid) upd(L, l, mid, rt << 1, val);
	else upd(L, mid + 1, r, rt << 1 | 1, val);
	push_up(rt);
}

int querysum(int L, int R, int l, int r, int rt) {
	if(L <= l && r <= R) {
		return tree[rt];
	}
	int mid = l + r >> 1;
	push_down(rt);
	int res = 0;
	if(L <= mid) res = (res + querysum(L, R, l, mid, rt << 1));
	if(R > mid) res = (res +querysum(L, R, mid + 1, r, rt << 1 | 1));
	return res;
}

int querymax(int L, int R, int l, int r, int rt) {
	if(L <= l && r <= R) {
		return ma[rt];
	}
	int mid = l + r >> 1;
	push_down(rt);
	int res = -0x3f3f3f3f;
	if(L <= mid) res = max(res, querymax(L, R, l, mid, rt << 1));
	if(R > mid) res = max(res, querymax(L, R, mid + 1, r, rt << 1 | 1));
	return res;
}

int querymin(int L, int R, int l, int r, int rt) {
	if(L <= l && r <= R) {
		return mi[rt];
	}
	int mid = l + r >> 1;
	push_down(rt);
	int res = 0x3f3f3f3f;
	if(L <= mid) res = min(res, querymin(L, R, l, mid, rt << 1));
	if(R > mid) res = min(res, querymin(L, R, mid + 1, r, rt << 1 | 1));
	return res;
}

void onlymson(int x, int z) {
	if(dep[e[x].first] > dep[e[x].second]) x = e[x].first;
	else x = e[x].second;
	upd(dfn[x], 1, n, 1, z);
}

void opp_mchain(int x, int y, int z = 1) {
	while(top[x] != top[y]) {
		if(dep[top[x]] < dep[top[y]]) swap(x, y);
		updata(dfn[top[x]], dfn[x], 1, n, 1);
		x = fa[top[x]];
	}
	if(dep[x] > dep[y]) swap(x, y);
	updata(dfn[x] + 1, dfn[y], 1, n, 1);
}

int qchainsum(int x, int y) {
	int ret = 0;
	while(top[x] != top[y]) {
		if(dep[top[x]] < dep[top[y]]) swap(x, y);
		ret = (ret + querysum(dfn[top[x]], dfn[x], 1, n, 1));
		x = fa[top[x]];
	}
	if(dep[x] > dep[y]) swap(x, y);
	ret = (ret + querysum(dfn[x] + 1, dfn[y], 1, n, 1));
	return ret;
}

int qchainmax(int x, int y) {
	int ret = -INF;
	while(top[x] != top[y]) {
		if(dep[top[x]] < dep[top[y]]) swap(x, y);
		ret = max(ret, querymax(dfn[top[x]], dfn[x], 1, n, 1));
		x = fa[top[x]];
	}
	if(dep[x] > dep[y]) swap(x, y);
	ret = max(ret, querymax(dfn[x] + 1, dfn[y], 1, n, 1));
	return ret;
}

int qchainmin(int x, int y) {
	int ret = INF;
	while(top[x] != top[y]) {
		if(dep[top[x]] < dep[top[y]]) swap(x, y);
		ret = min(ret, querymin(dfn[top[x]], dfn[x], 1, n, 1));
		x = fa[top[x]];
	}
	if(dep[x] > dep[y]) swap(x, y);
	ret = min(ret, querymin(dfn[x] + 1, dfn[y], 1, n, 1));
	return ret;
}

signed main() {
	scanf("%d", &n);
	for(int i = 1, a, b, c; i < n; i ++) {
		scanf("%d %d %d", &a, &b, &c);
		a ++, b ++;
		e[i] = make_pair(a, b);
		ade(a, b, c), ade(b, a, c);
	}
	dfs1(1, 0);
	dfs2(1, 0);
	build(1, n, 1);
	scanf("%d", &m);
	char op[15];
	int x, y;
	while(m --) {
		scanf("%s %d %d", op, &x, &y);
		x ++, y ++;
		if(op[0] == 'C') onlymson(x - 1, y - 1);
		if(op[0] == 'N') opp_mchain(x, y, -1);
		if(op[0] == 'S') printf("%d\n", qchainsum(x, y));
		if(op[1] == 'A') printf("%d\n", qchainmax(x, y));
		if(op[1] == 'I') printf("%d\n", qchainmin(x, y));
	}
	return 0;
}
全部评论

相关推荐

09-30 12:39
门头沟学院 C++
点赞 评论 收藏
分享
三年之期已到我的offer快到碗里来:9硕都比不上9本
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务