bzoj1103

dfs序

dfs序真神奇

dfs求出入栈时刻和出栈时刻,然后在in和out分别打上1和-1就能统计路径和了。

其实这里dfs序能够让我们求一个点处于哪些节点的子树内,而一个节点只处于从自己到跟路径的节点的。

这里的dfs序有些像括号序列,如果一个点不在另一个点的子树内,那么也就不在另一个点的括号内,那么另一个点的括号也闭合了,+1-1抵消

#include<bits/stdc++.h>
using namespace std;
const int N = 250010;
int n, m, top, cnt;
int st[N], in[N], out[N];
vector<int> G[N];
struct BIT {
    int tree[N << 1];
    int lowbit(int i)
    {
        return i & (-i);
    }
    void update(int pos, int delta)
    {
        for(int i = pos; i <= n * 2 + 1; i += lowbit(i)) tree[i] += delta;
    }
    int query(int pos)
    {
        int ret = 0;
        for(int i = pos; i; i -= lowbit(i)) ret += tree[i];
        return ret;
    }
} t;
void dfs(int u, int last)
{
    in[u] = ++cnt;
    for(int i = 0; i < G[u].size(); ++i)
    {
        int v = G[u][i];
        if(v == last) continue;
        dfs(v, u);
    }
    out[u] = ++cnt;
}
int main()
{
    scanf("%d", &n);
    for(int i = 1; i < n; ++i)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1, 0);
    scanf("%d", &m);
    for(int i = 2; i <= n; ++i)
    {
        t.update(in[i], 1);
        t.update(out[i], -1);
    }
    for(int i = 1; i < n + m; ++i)
    {
        char opt[10];
        int u, v;
        scanf("%s", opt);
        if(opt[0] == 'A')
        {
            scanf("%d%d", &u, &v);
            t.update(in[v], -1);
            t.update(out[v], 1);
        }
        if(opt[0] == 'W')
        {
            scanf("%d", &u);
            printf("%d\n", t.query(in[u]));
        }
    }
    return 0;
}
View Code

 

posted @ 2017-07-26 14:51  19992147  阅读(123)  评论(0编辑  收藏  举报