WA 0 求调(玄关)
查看原帖
WA 0 求调(玄关)
726139
残阳如血楼主2024/5/21 21:14

样例可以过,但是数据点一个没过。

// 为了方便,将所有下标 +1,即从 [0,n-1] 变为 [1,n]
#include <string>
#include <vector>
#include <memory>
#include <cstring>
#include <iostream>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
// #define DEBUG
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);
}

// 动态开点线段树
struct TreeNode {
	int w, lzy; // w 存储 1 的个数
	std::unique_ptr<TreeNode> lson, rson;
	TreeNode() : w(0), lzy(INF), lson(nullptr), rson(nullptr) {}
};

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(std::unique_ptr<TreeNode> &u, int l, int r, int x) {
	u->lzy = x;
	if (x == 1) u->w = r - l + 1;
	else u->w = 0;
}
void pushup(std::unique_ptr<TreeNode> &u) { u->w = u->lson->w + u->rson->w; }
void pushdown(std::unique_ptr<TreeNode> &u, int l, int r) {
	if (!u->lson) u->lson = std::unique_ptr<TreeNode>(new TreeNode);
	if (!u->rson) u->rson = std::unique_ptr<TreeNode>(new TreeNode);
	if (u->lzy == INF) return ;
	int mid = l + r >> 1;
	maketag(u->lson, l, mid, u->lzy);
	maketag(u->rson, mid + 1, r, u->lzy);
	u->lzy = INF;
}

int query(std::unique_ptr<TreeNode> &u, int l, int r, int L, int R, int x) { // 查询 [l,r] 有多少个 x
	if (outRange(l, r, L, R)) return 0;
	if (inRange(l, r, L, R)) return (x == 1 ? u->w : r - l + 1 - u->w);
	int mid = l + r >> 1;
	pushdown(u, l, r);
	return query(u->lson, l, mid, L, R, x) + query(u->rson, mid + 1, r, L, R, x);
}

void update(std::unique_ptr<TreeNode> &u, int l, int r, int L, int R, int x) { // [l,r] 赋值为 x
	if (outRange(l, r, L, R)) return ;
	if (inRange(l, r, L, R)) { maketag(u, l, r, x); return ; }
	int mid = l + r >> 1;
	pushdown(u, l, r);
	update(u->lson, l, mid, L, R, x);
	update(u->rson, 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, 1);
	std::unique_ptr<TreeNode> root(new TreeNode);
	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 += query(root, 1, n, dfn[top[x]], dfn[x], 0);
				update(root, 1, n, dfn[x], dfn[top[x]], 1);
				x = fa[top[x]];
			}
			if (dfn[x] > dfn[y]) std::swap(x, y);
			res += query(root, 1, n, dfn[x], dfn[y], 0);
			update(root, 1, n, dfn[x], dfn[y], 1);
			std::cout << res << '\n';
		} else {
			// 将 x 的子树(包含 x)全部赋值为 0
			std::cout << query(root, 1, n, dfn[x], dfn[x] + size[x] - 1, 1) << '\n';
			update(root, 1, n, dfn[x], dfn[x] + size[x] - 1, 0);
		}
	}
	std::cout.flush();
	return 0;
}
2024/5/21 21:14
加载中...