• ZOJ 3686 A Simple Tree Problem


    ZOJ月赛,题目描述确实很simple。。。

    那么就是把一棵树转换为线性表,使得整个子树都在一个区间里。。

    方法就是前序遍历了,遍历完一颗树它的根节点都连续的存在它后面了。

    对于每一个节点要存它和它子树所在区间,

    l显然是该节点的值,r就是它最后一个子节点的r,dfs的时候返回就可以了。

    对于叶子节点来说,r就是它本身,可以把返回的值初始化为l,这样就不用判断是否为叶子了。


    其次就是说区间的xor问题。。由于是求1的个数,那么就是求sum值了。

    对于一个区间,如果xor了,等价于sum=r-l+1-sum。


    另外就是困扰我多时的pushdown问题。。。

    由于是跟not only success学的,而他那里面都是代码,没有教程,所以pushdown很弱。。。

    现在大致是明白了懒惰标记跟本节点无关,pushdown的时候处理本节点的懒惰标记、子节点的懒惰标记和sum值。

    而update到了符合条件的区间的时候,需要处理本节点的sum值和懒惰标记

    而que的时候就不用了。。。。


    实在不明白在知道这些事情之前,自己怎么ac的题的。。。大致都跟not only success代码对照过才交的。。。完全没有技术含量。。


    #include<cstdio>
    #include<vector>
    #include<iostream>
    #define X 100010
    using namespace std;
    
    vector<int>e[X];
    int hl[X],hr[X],top;
    int dfs(int u){
        int x,v,i,n;
        n=e[u].size();
        hl[u]=top;x=top++;
        for(i=0;i<n;i++){
            v=e[u][i];
            x=dfs(v);
        }
        hr[u]=x;
        return x;
    }
    
    #define lson l,mid,rt*2
    #define rson mid+1,r,rt*2+1
    int sum[X*4],a[X*4],ll,rr,c;
    void pushup(int rt){
        sum[rt]=sum[rt*2]+sum[rt*2+1];
    }
    void pushdown(int l,int r,int rt){
        if(a[rt]){
            a[rt*2]^=1;a[rt*2+1]^=1;a[rt]=0;
            int mid=l+r>>1;
            sum[rt*2]=(mid-l+1)-sum[rt*2];
            sum[rt*2+1]=(r-mid)-sum[rt*2+1];
        }
    }
    void update(int l,int r,int rt){
        if(ll<=l&&rr>=r){
            a[rt]^=1;
            sum[rt]=r-l+1-sum[rt];
            return ;
        }
        pushdown(l,r,rt);
        int mid=l+r>>1;
        if(ll<=mid)update(lson);
        if(rr> mid)update(rson);
        pushup(rt);
    }
    int que(int l,int r,int rt){
        if(ll<=l&&rr>=r){
            return sum[rt];
        }
        pushdown(l,r,rt);
        int as=0;
        int mid=l+r>>1;
        if(ll<=mid)as=que(lson);
        if(rr>mid)as+=que(rson);
        return as;
    }
    int main(){
        int i,j,u,v,n,m;
        char str[5];
        while(~scanf("%d%d",&n,&m)){
            for(i=1;i<=n;i++){
                hl[i]=hr[i]=0;
                e[i].clear();
            }
            for(i=2;i<=n;i++){
                scanf("%d",&j);
                e[j].push_back(i);
            }
            top=1;dfs(1);
    
            for(i=0;i<top*4;i++)a[i]=sum[i]=0;
            while(m--){
                scanf("%s%d",str,&i);
                ll=hl[i];rr=hr[i];
                if(str[0]=='o')update(1,top,1);
                else printf("%d\n",que(1,top,1));
            }
            puts("");
        }
        return 0;
    
    }


  • 相关阅读:
    4. Qt的容器类
    hdu 4507 数位dp(求和,求平方和)
    MVC3和MVC4中CRUD操作
    SSL 中证书能否够使用IP而不是域名
    TinyXml快速入门(一)
    C++ TinyXml操作(含源码下载)
    Tinyxml 操作XML
    msxml 操作xml
    MFC中全局变量的定义及使用
    VC++中操作XMLWin32实例
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3013717.html
Copyright © 2020-2023  润新知