ZOJ 3686 A Simple Tree Problem 线段树

如果把一颗树跑一遍拓扑排序,会发现每颗子树都在一个区间里。

那么对子树的操作就变成对区间的操作。

#include
#include
#include
#include<string.h>
#include

using namespace std;

const int MAXN=100100;

int n,m;
int t;

int id[MAXN];
int num[MAXN];
vector<int> g[MAXN];

int calnum(int u)
{
    int x=1;
    for(int i=0;i)
        x+=calnum(g[u][i]);
    return num[u]=x;
}

int topo(int u)
{
    for(int i=0;i)
        topo(g[u][i]);
    id[u]=t--;
    return 0;
}

int sum[MAXN<<2];
int flag[MAXN<<2];
int build()
{
    memset(sum,0,sizeof(sum));
    memset(flag,0,sizeof(flag));
}
int PushDown(int idx,int l,int r)
{
    if(flag[idx])
    {
        int mid=(r+l)>>1;
        flag[idx<<1]^=1;
        sum[idx<<1]=mid-l+1-sum[idx<<1];

        flag[idx<<1|1]^=1;
        sum[idx<<1|1]=r-mid-sum[idx<<1|1];

        flag[idx]=0;
    }
    return 0;
}
int update(int idx,int l,int r,int tl,int tr)
{
    if(tl<=l&&tr>=r)
    {
        flag[idx]^=1;
        sum[idx]=r-l+1-sum[idx];
        return 0;
    }
    PushDown(idx,l,r);
    int mid=(r+l)>>1;
    if(tl<=mid)update(idx<<1,l,mid,tl,tr);
    if(tr>mid)update(idx<<1|1,mid+1,r,tl,tr);
    sum[idx]=sum[idx<<1]+sum[idx<<1|1];
    return 0;
}

int query(int idx,int l,int r,int tl,int tr)
{
    if(tl<=l&&tr>=r)
        return sum[idx];
    PushDown(idx,l,r);
    int mid=(r+l)>>1;
    int x=0;
    if(tl<=mid)
        x+=query(idx<<1,l,mid,tl,tr);
    if(tr>mid)
        x+=query(idx<<1|1,mid+1,r,tl,tr);
    return x;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;i++)
            g[i].clear();
        for(int i=2;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            g[x].push_back(i);
        }
        calnum(1);
        t=n;
        topo(1);
        build();
        for(int i=1;i<=m;i++)
        {
            char op[10];
            int u;
            scanf("%s%d",op,&u);
            if(op[0]=='o')
                update(1,1,n,id[u],id[u]+num[u]-1);
            else
            {
                int x=query(1,1,n,id[u],id[u]+num[u]-1);
                printf("%d\n",x);
            }
        }
        printf("\n");
    }
    return 0;
}
View Code

 

 

转载于:https://www.cnblogs.com/BMan/p/3415167.html

你可能感兴趣的:(ZOJ 3686 A Simple Tree Problem 线段树)