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;

}


原文地址:https://www.cnblogs.com/xinyuyuanm/p/3013717.html