[CF877E] Danil and a Part-time Job

[CF877E] Danil and a Part-time Job - DFS序,线段树

Description

有一棵 (n) 个点的树,根结点为 (1) 号点,每个点的权值都是 (1)(0),操作两种,询问一个点 (x) 的子树里有多少个 (1),将一个点 (x) 的子树中所有节点取反

Solution

DFS 序转化为序列问题后线段树维护每个区间 1 的个数即可

#include <bits/stdc++.h>
using namespace std;

#define int long long

const int N = 1000005;

vector<int> g[N];
int dfn[N], fin[N], ind;

void dfs(int p, int from)
{
    dfn[p] = ++ind;
    for (int q : g[p])
    {
        if (q == from)
            continue;
        dfs(q, p);
    }
    fin[p] = ind;
}

// segtree

int a[N], tag[N];

void pushup(int p)
{
    a[p] = a[p * 2] + a[p * 2 + 1];
}

void pushdown(int p, int l, int r)
{
    if (tag[p])
    {
        tag[p] = 0;
        a[p * 2] = ((l + r) / 2 - l + 1) - a[p * 2];
        tag[p * 2] ^= 1;
        a[p * 2 + 1] = (r - (l + r) / 2) - a[p * 2 + 1];
        tag[p * 2 + 1] ^= 1;
    }
}

void build(int p, int l, int r, int *src)
{
    if (l == r)
    {
        a[p] = src[l];
    }
    else
    {
        build(p * 2, l, (l + r) / 2, src);
        build(p * 2 + 1, (l + r) / 2 + 1, r, src);
        pushup(p);
    }
}

void modify(int p, int l, int r, int ql, int qr)
{
    if (l > qr || r < ql)
        return;
    if (l >= ql && r <= qr)
    {
        a[p] = r - l + 1 - a[p];
        tag[p] ^= 1;
    }
    else
    {
        pushdown(p, l, r);
        modify(p * 2, l, (l + r) / 2, ql, qr);
        modify(p * 2 + 1, (l + r) / 2 + 1, r, ql, qr);
        pushup(p);
    }
}

int query(int p, int l, int r, int ql, int qr)
{
    if (l > qr || r < ql)
        return 0;
    if (l >= ql && r <= qr)
        return a[p];
    pushdown(p, l, r);
    return query(p * 2, l, (l + r) / 2, ql, qr) + query(p * 2 + 1, (l + r) / 2 + 1, r, ql, qr);
}

int val[N], seq[N];
int n, m;

signed main()
{
    ios::sync_with_stdio(false);

    cin >> n;
    for (int i = 2; i <= n; i++)
    {
        int fa;
        cin >> fa;
        g[fa].push_back(i);
    }

    for (int i = 1; i <= n; i++)
    {
        cin >> val[i];
    }

    dfs(1, 0);

    for (int i = 1; i <= n; i++)
    {
        seq[dfn[i]] = val[i];
    }

    build(1, 1, n, seq);

    cin >> m;

    for (int i = 1; i <= m; i++)
    {
        string op;
        int x;
        cin >> op >> x;
        if (op == "get")
        {
            cout << query(1, 1, n, dfn[x], fin[x]) << endl;
        }
        else
        {
            modify(1, 1, n, dfn[x], fin[x]);
        }
    }
}
原文地址:https://www.cnblogs.com/mollnn/p/14631885.html