zoukankan      html  css  js  c++  java
  • ZOJ 3686 A Simple Tree Problem 线段树

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

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

    #include<stdio.h>
    #include<vector>
    #include<iostream>
    #include<string.h>
    #include<stdlib.h>
    
    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<g[u].size();i++)
            x+=calnum(g[u][i]);
        return num[u]=x;
    }
    
    int topo(int u)
    {
        for(int i=0;i<g[u].size();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
    ",x);
                }
            }
            printf("
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    codeforces 169 div2 C
    poj 1062(最短路)
    sgu 118
    sgu 101
    poj 2446二分图匹配
    ural 1129 (求数据)
    C#中抽象类和接口的区别(转)
    在.net(C# or vb.net)中,Appplication.Exit 还是 Form.Close有什么不同?
    一道爱出的题目,就是前面两个数相加 用递归方法实现
    C#冒泡排序
  • 原文地址:https://www.cnblogs.com/BMan/p/3415167.html
Copyright © 2011-2022 走看看