样例过不去,HELP!!!
查看原帖
样例过不去,HELP!!!
726139
残阳如血楼主2024/5/19 09:58
// 为了方便,将所有下标 +1,即从 [0,n-1] 变为 [1,n]
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
const int N = 1e5 + 10;
const int INF = 2e9;

int n, q, cnt;
std::vector<int> g[N]; // 不包含父亲节点
int fa[N], dep[N], son[N], size[N], top[N], dfn[N], rnk[N];

void dfs1(int u) {
	dep[u] = dep[fa[u]] + 1, size[u] = 1;
	// 更新深度以及子树大小
	for (auto v : g[u]) {
		dfs1(v);
		size[u] += size[v];
		if (size[v] > size[son[u]]) son[u] = v;
		// 当前没有重儿子或者这颗子树的大小大于重儿子子树的大小时,重儿子变为当前的儿子
	}
}

void dfs2(int u, int ftop) {
	top[u] = ftop, rnk[dfn[u] = ++cnt] = u;
	if (!son[u]) return ;
	dfs2(son[u], ftop);
	for (auto v : g[u])
		if (v != son[u]) dfs2(v, v);
}

namespace SegmentTree {
	int w[N << 2], lzy[N << 2];
	// 记录区间中 1 的个数
	bool inRange(int l, int r, int L, int R) { return l >= L && r <= R; }
	bool outRange(int l, int r, int L, int R) { return l > R || r < L; }
	void maketag(int u, int l, int r, int x) { lzy[u] = x, w[u] = (r - l + 1) * x; }
	void pushdown(int u, int l, int r) {
		if (lzy[u] == INF) return ;
		int mid = l + r >> 1;
		maketag(u, l, mid, lzy[u]);
		maketag(u, mid + 1, r, lzy[u]);
		lzy[u] = INF;
	}
	void pushup(int u) { w[u] = w[u * 2] + w[u * 2 + 1]; }
	int query(int u, int l, int r, int L, int R) { // 查询区间中 1 的个数
		if (outRange(l, r, L, R)) return 0;
		if (inRange(l, r, L, R)) return w[u];
		pushdown(u, l, r);
		int mid = l + r >> 1;
		return query(u * 2, l, mid, L, R) + query(u * 2 + 1, mid + 1, r, L, R);
	}
	void update(int u, int l, int r, int L, int R, int x) { // 区间赋值为 x
		if (outRange(l, r, L, R)) return ;
		if (inRange(l, r, L, R)) { maketag(u, l, r, x); return ; }
		pushdown(u, l, r);
		int mid = l + r >> 1;
		update(u * 2, l, mid, L, R, x);
		update(u * 2 + 1, mid + 1, r, L, R, x);
		pushup(u);
	}
}



int main() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cin >> n;
	// 重儿子为 -1 表示当前没有重儿子
	for (int i = 2; i <= n; ++i) {
		std::cin >> fa[i]; // 可以直接读入 fa[i]
		++fa[i];
		g[fa[i]].push_back(i); // 存储 fa[i] 的所有儿子
	}
	dfs1(1);
	dfs2(1, 0);
	std::string op; int x;
	for (std::cin >> q; q; --q) {
		std::cin >> op >> x, ++x;
		if (op == "install") {
			// 将 x-0 的路径上全部赋值为 1
			int res = 0, y = 1;
			while (top[x] != top[y]) {
				if (dep[top[x]] < dep[top[y]]) std::swap(x, y);
				res += dfn[x] - dfn[top[x]] + 1 - SegmentTree::query(1, 1, n, dfn[top[x]], dfn[x]);
				SegmentTree::update(1, 1, n, dfn[x], dfn[top[x]], 1);
				x = fa[top[x]];
			}
			int p = max(dfn[x], dfn[y]), q = min(dfn[x], dfn[y]); // q 是 p 的祖先
			res += p - q + 1 - SegmentTree::query(1, 1, n, q, p);
			SegmentTree::update(1, 1, n, q, p, 1);
			std::cout << res << '\n';
		} else {
			// 将 x 的子树(包含 x)全部赋值为 0
			std::cout << SegmentTree::query(1, 1, n, dfn[x], dfn[x] + size[x] - 1) << '\n';
			SegmentTree::update(1, 1, n, dfn[x], dfn[x] + size[x] - 1, 0);
		}
	}
	std::cout.flush();
	return 0;
}
2024/5/19 09:58
加载中...