zoj 3686 A Simple Tree Problem (线段树)

Solution:

  根据树的遍历道的时间给树的节点编号,记录下进入节点和退出节点的时间。这个时间区间覆盖了这个节点的所有子树,可以当做连续的区间利用线段树进行操作。

/*
       线段树
*/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#define lson x<<1
#define rson x<< 1 | 1
using namespace std;

const int MAX = 111111;
int w[MAX], to[MAX];
int tl[MAX << 3], tr[MAX << 3], flag[MAX << 3], sum[MAX << 3][2];
int l, r;
struct Edge {
    int v, ne;
} edge[MAX << 1];

int head[MAX], cnt, num;

void Dfs ( int u )
{
    w[u] = ++num;
    for ( int i = head[u]; i != 0; i = edge[i].ne ) {
        Dfs ( edge[i].v );
    }
    to[u] = num;
}

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

void build ( int x, int l, int r )
{
    flag[x] = sum[x][0] = sum[x][1] = 0;
    tl[x] = l, tr[x] = r;
    if ( l == r ) {
        sum[x][0] = 1;
        return ;
    }
    int mid = ( l + r ) >> 1;
    build ( lson, l, mid ), build ( rson, mid + 1, r );
    sum[x][0] += sum[lson][0] + sum[rson][0];
}

void push ( int x )
{
    if ( flag[x] == 0 ) return;
    flag[x] = 0;
    flag[lson] ^= 1;
    swap ( sum[lson][0], sum[lson][1] );
    flag[rson] ^= 1;
    swap ( sum[rson][0], sum[rson][1] );
}
void updata ( int x )
{
    sum[x][0] = sum[lson][0] + sum[rson][0];
    sum[x][1] = sum[lson][1] + sum[rson][1];
}
void modify ( int x )
{
    if ( tl[x] >= l && tr[x] <= r ) {
        flag[x] ^= 1;
        swap ( sum[x][0], sum[x][1] );
        return ;
    }
    push ( x );
    int mid = ( tl[x] + tr[x] ) >> 1;
    if ( l <= mid ) modify ( lson );
    if ( r > mid ) modify ( rson );
    updata ( x );
}

int query ( int x )
{
    if ( tl[x] >= l && tr[x] <= r ) {
        return sum[x][1];
    }
    push ( x );
    int mid = ( tl[x] + tr[x] ) >> 1, ans = 0;
    if ( l <= mid ) ans += query ( lson );
    if ( r > mid ) ans += query ( rson );
    updata ( x );
    return ans;
}

int n, m;

void init()
{
    num = cnt = 0;
    memset ( head, 0, sizeof head );
}
int main()
{
    while ( scanf ( "%d %d", &n, &m ) != EOF ) {
        init();
        for ( int i = 2, v; i <= n; i++ ) {
            scanf ( "%d", &v );
            addE ( v, i );
        }
        Dfs ( 1 );
        scanf ( "%d", &m );
        build ( 1, 1, n );
        char cmd[10];
        for ( int i = 1, u; i <= m; ++i ) {
            scanf ( "%s %d", cmd, &u );
            l = w[u], r = to[u];
            if ( cmd[0] == 'o' ) {
                modify ( 1 );
            } else {
                printf ( "%d
", query ( 1 ) );
            }
        }
        putchar(10);
    }
}
View Code
原文地址:https://www.cnblogs.com/keam37/p/4661681.html