zoukankan      html  css  js  c++  java
  • 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;
    
    }


  • 相关阅读:
    mac使用vnc远程登录ubuntu16.04桌面
    last的用法
    MAC笔记本安装telnet
    lsyncd自动同步配置
    四则运算——安卓版
    敏捷开发方法综述
    数组2——数组首尾相接,求最大子数组
    数组1——求一个数组的最大子数组
    《构建之法》阅读笔记04
    学习进度条——第四周
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3013717.html
Copyright © 2011-2022 走看看