首页 > 技术文章 > 洛谷P2146 [NOI2015]软件包管理器

kma093 2019-08-02 17:07 原文

题目链接

走这里

题目分析

对不起我就来水个博客
好像这段时间一直很颓,但是什么事情都不干又良心不安,所以就来颓个树剖。
说正事。
最开始做这个题的时候sb了一下,因为虽然可以当做染色染0和1,不知道怎么统计状态变化的软件包的数量,后来发现我们在线段树上维护的\(sum\)的变化值其实就是这段区间状态变化的软件包的数量,然后我们可以偷个懒不用区间查询,直接输出线段树根节点的\(sum\)变化量即可。

代码

贴一个极致压行的80行代码,第一次10min以内过树剖题,有点感动。

#include <bits/stdc++.h>
#define ls(p) p << 1
#define rs(p) p << 1 | 1 
#define N (200000 + 10)
using namespace std;
inline int read() {
	int cnt = 0, f = 1; char c = getchar();
	while (!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
	while (isdigit(c)) {cnt = (cnt << 3) + (cnt << 1) + c - '0'; c = getchar();}
	return cnt * f;
}
int nxt[N], to[N], first[N], tot, n, q, x;
void Add(int x, int y) {nxt[++tot] = first[x], first[x] = tot, to[tot] = y;}
int dep[N], siz[N], father[N], son[N], id[N], top[N], idx;
char ope[20];
void dfs_(int x, int fa) {
	dep[x] = dep[fa] + 1, siz[x] = 1, father[x] = fa;
	for (register int i = first[x]; i; i = nxt[i]) {
		int v = to[i];
		if (v == fa) continue;
		dfs_(v, x);
		siz[x] += siz[v];
		if (siz[son[x]] < siz[v]) son[x] = v;
	}
}
void dfs__(int x, int tp) {
	top[x] = tp, id[x] = ++idx;
	if (son[x]) dfs__(son[x], tp);
	for (register int i = first[x]; i; i = nxt[i]) {
		int v = to[i];
		if (!id[v]) dfs__(v, v);
	}
}
struct segmentree {
	int l, r, sum, tag;
	#define l(p) tree[p].l
	#define r(p) tree[p].r
	#define sum(p) tree[p].sum
	#define tag(p) tree[p].tag 
}tree[N << 2];
void push_up(int p) {sum(p) = sum(ls(p)) + sum(rs(p));}
void push_rev(int p, int k) {sum(p) = (k ? (r(p) - l(p) + 1) : 0), tag(p) = k;}
void push_down(int p) {
	if (tag(p) >= 0) push_rev(ls(p), tag(p)), push_rev(rs(p), tag(p)), tag(p) = -1;
}
void build(int p, int l, int r) {
	l(p) = l, r(p) = r;
	if (l == r) {tag(p) = -1; return;}
	int mid = (l + r) >> 1;
	build (ls(p), l, mid), build (rs(p), mid + 1, r);
	push_up(p);
}
void modify(int p, int l, int r, int d) {
	if (l <= l(p) && r >= r(p)) { push_rev(p, d); return;}
	push_down(p);
	int mid = (l(p) + r(p)) >> 1;
	if (l <= mid) modify (ls(p), l, r, d);
	if (r > mid) modify(rs(p), l, r, d);
	push_up(p); 
}
void Modify(int u, int v, int d) {
	while (top[u] != top[v]) {
		if (dep[top[u]] < dep[top[v]]) swap(u, v);
		modify(1, id[top[u]], id[u], d);
		u = father[top[u]];
	}
	dep[u] < dep[v] ? modify(1, id[u], id[v], d) : modify(1, id[v], id[u], d);
}
signed main() {
	n = read(); 
	for (register int i = 2; i <= n; ++i) x = read() + 1, Add(x, i), Add(i, x);
	dfs_(1, 0), dfs__(1, 1), build (1, 1, n);
	q = read();
	for (register int i = 1; i <= q; i++) {
		scanf("%s", ope + 1); int ans = sum(1);
		x = read() + 1, ope[1] == 'i' ? Modify(x, 1, 1) : modify(1, id[x], id[x] + siz[x] - 1, 0); 
		printf("%d\n", abs(ans - sum(1)));
	}
	return 0;
}

推荐阅读