POJ 3321 Apple Tree

题目链接:POJ 3321 Apple Tree

题目大意:
POJ 3321 Apple Tree

题解:
\(dfs\)序的两个数组\(in\),\(out\)记录某结点进入和出来的时间,则对于一个结点\(u\),其子树中某一结点\(v\)满足\(in_u < in_v < out_v < out_u\)。
用树状数组存储各时间戳所对应的结点的状况,则\(getSum(out_u) - getSum(in_u - 1)\)所得结果就是以\(u\)为根的子树的状况。
由于每次进入或者出来时间戳都会加一,所以树状数组的大小应为\(2 \times n\)。

#include <iostream>
using namespace std;

struct Edge {
    int v, next;
} edge[100010];
char s;
int x;
int in[100010], out[100010], sum[200010], tot;
int n, m, cnt, head[100010];
bool vis[100010];

void addEdge(int u, int v) {
    edge[++cnt].v = v;
    edge[cnt].next = head[u];
    head[u] = cnt;
}

int lowbit(int x) { return x & (-x); }

void dfs(int x) {
    in[x] = ++tot;
    for (int i = head[x]; i; i = edge[i].next) {
        dfs(edge[i].v);
    }
    out[x] = ++tot;
}

void update(int x, int add) {  // 树状数组更新
    while (x <= 2 * n) {
        sum[x] += add;
        x += lowbit(x);
    }
}

int getSum(int x) {
    int ans = 0;
    while (x > 0) {
        ans += sum[x];
        x -= lowbit(x);
    }
    return ans;
}

int main() {
    ios::sync_with_stdio(false);
    cin >> n;
    for (int i = 1; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        addEdge(u, v);
    }
    dfs(1);
    for (int i = 1; i <= n; ++i) {
        update(in[i], 1);
        vis[i] = 1;
    }
    cin >> m;
    while (m--) {
        cin >> s >> x;
        if (s == 'C') {
            if (vis[x]) {
                update(in[x], -1);
            } else {
                update(in[x], 1);
            }
            vis[x] ^= 1;
        }
        if (s == 'Q') {
            cout << getSum(out[x]) - getSum(in[x] - 1) << endl;
        }
    }
    return 0;
}
上一篇:Python获取IP地址对应的地理位置信息!


下一篇:2020全国普通高校大学生竞赛排行榜