[Luogu] 软件包管理器

Posted xayata

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Luogu] 软件包管理器相关的知识,希望对你有一定的参考价值。

https://www.luogu.org/problemnew/show/P2146

几乎是一个裸题

#include<cstdio>
#include<cstring>
#include<algorithm>
 
#define ls (p << 1)
#define rs ((p << 1) | 1)
#define mid ((l + r) >> 1)

const int N = 200010, M = N << 2;
using namespace std;

int n, Q, last[N], pre[N], now[N], son[N], tot, a[N], cnt, w[N], size[N];
int hson[N], top[N], fa[N], dep[N];
char op[12];

struct Tree {
    int sum[M], cov[M], size[M];
    void down(int p) {
        if (cov[p] != -1) {
            sum[ls] = size[ls] * cov[p], sum[rs] = size[rs] * cov[p];
            cov[ls] = cov[rs] = cov[p], cov[p] = -1;
        }
    }
    void build(int p, int l, int r) {
        if (l == r) {
            sum[p] = 0, cov[p] = -1, size[p] = 1;
            return;
        }
        build(ls, l, mid), build(rs, mid + 1, r);
        sum[p] = sum[ls] + sum[rs], size[p] = size[ls] + size[rs];
    }
    void change(int p, int l, int r, int a, int b, int v) {
        if (l == a && r == b) {
            sum[p] = v * size[p], cov[p] = v;
            return;
        }
        down(p);
        if (b <= mid) change(ls, l, mid, a, b, v);
        else if (a > mid) change(rs, mid + 1, r, a, b, v);
        else change(ls, l, mid, a, mid, v), change(rs, mid + 1, r, mid + 1, b, v);
        sum[p] = sum[ls] + sum[rs];
    }
    int query(int p, int l, int r, int a, int b) {
        if (l == a && r == b) {
            return sum[p];
        }
        down(p);
        if (b <= mid) return query(ls, l, mid, a, b);
        else if (a > mid) return query(rs, mid + 1, r, a, b);
        else return query(ls, l, mid, a, mid) + query(rs, mid + 1, r, mid + 1, b);
    }
} Seg;

void add(int a, int b) {
    pre[++ tot] = now[a], now[a] = tot, son[tot] = b;
}
void dfs(int x) {
    size[x] = 1;
    for (int y = now[x]; y; y = pre[y])
        if (son[y] != fa[x]) {
            fa[son[y]] = x, dep[son[y]] = dep[x] + 1;
            dfs(son[y]), size[x] += size[son[y]];
            if (size[son[y]] > size[hson[x]]) hson[x] = son[y];
        }
}

void btree(int x, int tp) {
    w[x] = ++ cnt, a[cnt] = 0, top[x] = tp;
    if (hson[x]) btree(hson[x], tp);
    for (int y = now[x]; y; y = pre[y])
        if (son[y] != fa[x] && son[y] != hson[x])
            btree(son[y], son[y]);
    last[x] = cnt;
}

void answer(int a,int b) {
    int f1 = top[a], f2 = top[b], sum = 0, num = dep[b] - dep[a] + 1;
    while (f1 != f2) {
        if (dep[f1] < dep[f2]) swap(f1, f2), swap(a, b);
        sum += Seg.query(1, 1, n, w[f1], w[a]);
        Seg.change(1, 1, n, w[f1], w[a], 1);
        a = fa[f1], f1 = top[a];
    }
    if (dep[a] > dep[b]) swap(a, b);
    sum += Seg.query(1, 1, n, w[a], w[b]);
    Seg.change(1, 1, n, w[a], w[b], 1);
    printf("%d\n", num - sum);
}

int main() {
    scanf("%d", &n);
    for (int i = 2, x; i <= n; i ++) scanf("%d", &x), x ++, add(x, i);
    dfs(1), btree(1, 1), Seg.build(1, 1, n);
    scanf("%d", &Q);
    for (int i = 1, x; i <= Q; i ++) {
        scanf("%s%d", op, &x), x ++;
        if (op[0] == i) answer(1, x);
        else {
            printf("%d\n", Seg.query(1, 1, n, w[x], last[x]));
            Seg.change(1, 1, n, w[x], last[x], 0);
        }
    }
    return 0;
}

 

以上是关于[Luogu] 软件包管理器的主要内容,如果未能解决你的问题,请参考以下文章

luogu2146 [NOI2015]软件包管理器

Luogu P2146软件包管理器

Luogu P2146 软件包管理器(树链剖分+线段树)

如何使用Android片段管理器传递变量[重复]

massCode 一款优秀的开源代码片段管理器

Android:使用支持片段管理器时复制片段