ZOJ Monthly, March 2013 - A A Simple Tree Problem

http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=4959

题意:给一棵树,树的每个节点初始值为0,要求支持两种操作:

o k : 将k下的子树值取反

q k : 查询k下的子树值有多少个为1

思路:化树结构为线性,每个点管理一个区间。

View Code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 200005;

struct nd{
    int v,next;
}edge[maxn];

int hp[maxn];
int ls[maxn][2];//k管理的区间为[ls[k][0],ls[k][1]]

int as[maxn*8][3];

int ecnt;

int n,m;

void add(int u,int v)
{
    edge[ecnt].v = v;
    edge[ecnt].next = hp[u];
    hp[u] = ecnt++;
}


int dfs(int x)
{
    ls[x][0]= ls[x][1] = ecnt++;
    for(int i = hp[x]; i; i = edge[i].next){
        int v = edge[i].v;
        ls[x][1] = dfs(v);
    }
    return ls[x][1];
}

void doit(int rt){int tmp=as[rt][0];as[rt][0]=as[rt][1];as[rt][1]=tmp;}

void pushUp(int rt)
{
    as[rt][0] = as[rt<<1][0] + as[rt*2+1][0];
    as[rt][1] = as[rt<<1][1] + as[rt*2+1][1];
}

void pushDown(int rt)
{
    as[rt][2] ^= 1;
    as[rt*2][2] ^= 1;
    as[rt*2+1][2] ^= 1;
    doit(rt<<1);
    doit(rt*2+1);
}

void build(int rt,int l,int r)
{
    int mid = (l + r) >> 1;
    if(l==r){
        as[rt][0] = 1;
        as[rt][1] = 0;
        as[rt][2] = 0;
    }else{
        build(rt<<1,l,mid);
        build((rt<<1)+1,mid+1,r);
        pushUp(rt);
    }
}

void update(int rt,int l,int r,int L,int R)
{
    int mid = (l + r) >> 1;
    if(L<=l && r<=R){
        doit(rt);
        as[rt][2] ^= 1;
        return;
    }
    if(as[rt][2])pushDown(rt);
    if(L<=mid)update(rt<<1,l,mid,L,R);
    if(mid<R)update(rt*2+1,mid+1,r,L,R);
    pushUp(rt);
}

int ans;
void query(int rt,int l,int r,int L,int R)
{
    int mid = (l + r) >> 1;
    if(L<=l && r<=R){
        ans += as[rt][1];
        return;
    }
    if(as[rt][2])pushDown(rt);
    if(L<=mid)query(rt<<1,l,mid,L,R);
    if(mid<R)query(rt*2+1,mid+1,r,L,R);
    pushUp(rt);
}

int main()
{
    int i,k;
    while(scanf("%d %d",&n,&m)==2){

        for(i = 0; i <= n; ++ i)hp[i]=0;

        memset(as,0,sizeof(as));
        ecnt = 1;

        for(i = 2; i <= n; ++ i){
            scanf("%d",&k);
            add(k,i);
        }

        ecnt = 1;
        dfs(1);
        build(1,1,n);
        while(m--){
            char op[2];
            scanf("%s %d",op,&k);
            if(op[0]=='o')update(1,1,n,ls[k][0],ls[k][1]);
            else{
                ans = 0;
                query(1,1,n,ls[k][0],ls[k][1]);
                printf("%d\n",ans);
            }
        }
        puts("");
    }
    return 0;
}

 

posted on 2013-03-31 17:12  aigoruan  阅读(437)  评论(0编辑  收藏  举报

导航