【NOI2015】软件包管理器(树链剖分)
题目链接:https://loj.ac/problem/2130
题目链接:https://www.luogu.com.cn/problem/P2146
做法
貌似没有什么好说的,这个题很玄学。难点就是在于你得把点的编号$1-N$都加上一,然后稍加分析讨论就成了一个板子题了。
至于为什么必须把编号加一,暂时还不知道,就是瞎试碰巧AC的,此处留坑。
代码
#include <cstdio> #include <iostream> #define Re register using namespace std; const int maxN = 1e5 + 10; inline int read() { int x = 0; char ch = getchar(); while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar(); return x; } int N, Q, dep[maxN], fa[maxN], dfn[maxN], num[maxN], tot, top[maxN], hson[maxN], siz[maxN]; struct Edge { int nxt, to; } e[maxN << 1]; int cnte = 1, head[maxN]; inline void add_Edge(int i, int j) { e[++cnte].nxt = head[i], e[cnte].to = j, head[i] = cnte; } struct Segment_Tree { #define ls (rt << 1) #define rs (rt << 1 | 1) int sum, tag, l, r; } t[maxN << 2]; void dfs1(int u, int dad) { fa[u] = dad, dep[u] = dep[dad] + 1, siz[u] = 1; for (int i = head[u], v; i; i = e[i].nxt) { if ((v = e[i].to) == dad) continue; dfs1(v, u), siz[u] += siz[v]; if (siz[v] > siz[hson[u]]) hson[u] = v; } } void dfs2(int u, int TOP) { top[u] = TOP, dfn[u] = ++tot, num[tot] = u; if (!hson[u]) return; dfs2(hson[u], TOP); for (int i = head[u], v; i; i = e[i].nxt) { if ((v = e[i].to) != fa[u] && v != hson[u]) dfs2(v, v); } } inline void pushup(int rt) { t[rt].sum = t[ls].sum + t[rs].sum; } inline void pushdown(int rt) { if (t[rt].tag == -1) return; t[rs].sum = (t[rs].r - t[rs].l + 1) * t[rt].tag; t[ls].sum = (t[ls].r - t[ls].l + 1) * t[rt].tag; t[rs].tag = t[ls].tag = t[rt].tag; t[rt].tag = -1; } void build(int rt, int l, int r) { t[rt].l = l, t[rt].r = r; if (l == r) { t[rt].tag = -1; return; } int mid = (l + r) >> 1; build(ls, l, mid), build(rs, mid + 1, r); pushup(rt); } void update(int rt, int l, int r, int c) { if (l <= t[rt].l && t[rt].r <= r) { t[rt].sum = c * (t[rt].r - t[rt].l + 1); t[rt].tag = c; return; } pushdown(rt); int mid = (t[rt].l + t[rt].r) >> 1; if (l <= mid) update(ls, l, r, c); if (mid < r) update(rs, l, r, c); pushup(rt); } int qsum(int rt, int l, int r) { if (l <= t[rt].l && t[rt].r <= r) return t[rt].sum; pushdown(rt); int mid = (t[rt].l + t[rt].r) >> 1, res = 0; if (l <= mid) res += qsum(ls, l, r); if (mid < r) res += qsum(rs, l, r); return res; } int Qpath(int x, int y) { int res = 0, pos = max(x, y); while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); res += qsum(1, dfn[top[x]], dfn[x]); x = fa[top[x]]; } res += qsum(1, min(dfn[x], dfn[y]), max(dfn[x], dfn[y])); return (dep[pos] - res); } void update_path(int x, int y) { while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); update(1, dfn[top[x]], dfn[x], 1); x = fa[top[x]]; } update(1, min(dfn[x], dfn[y]), max(dfn[x], dfn[y]), 1); } int Qtree(int u) { return qsum(1, dfn[u], dfn[u] + siz[u] - 1); } void update_tree(int u) { update(1, dfn[u], dfn[u] + siz[u] - 1, 0); } int main() { N = read(); for (Re int i = 2, p; i <= N; ++i) p = read(), add_Edge((p + 1), i); dfs1(1, 0), dfs2(1, 1), build(1, 1, tot); Q = read(); string opt; while (Q--) { cin >> opt; Re int x = read(); ++x; if (opt == "install") { Re int ans1 = Qpath(x, 1); printf("%d\n", ans1); if (!ans1) continue; update_path(x, 1); } else { Re int ans2 = Qtree(x); printf("%d\n", ans2); if (!ans2) continue; update_tree(x); } } return 0; }

浙公网安备 33010602011771号