【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;
}

 

  

posted @ 2020-02-26 13:25  _Udumbara  阅读(145)  评论(0)    收藏  举报
/* */