Loading

CF877E

Description

给定一棵权值只能为 \(1\)\(0\) 的树,对其进行两种操作。

一种是将其中的某棵子树取反,另一种是询问某棵子树中 \(1\) 的个数。

Solution

比较板的线段树。

显然的,假设一棵大小为 \(x\) 的子树中有 \(y\) 个 1,那么这棵子树取反后就有 \(x-y\)\(1\)

题目只需要我们维护一种信息,然后这种信息的变换只有这一种方法,所以我们知道了这个性质就可以直接搞了。

根据区间修改维护懒标记的原理,当一个点的子树取反后,它的左右儿子都要取反,因此懒标记下传时也不断取反就可以了。

然后就做完了。

Code

#include<bits/stdc++.h>
#define maxn 2001000
#define INF 0x3f3f3f3f 
//#define int long long

using namespace std;

int n,m,tot,cnt;
int a[maxn],head[maxn],lazy[maxn];
int sum[maxn],val[maxn],fa[maxn];
int dfn[maxn],top[maxn],son[maxn];
int dep[maxn],siz[maxn],pre[maxn];
struct edge{int fr,to,nxt;}e[maxn];

int read(){
	int s=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
	return s*w;
}

void add(int fr,int to){
    e[++tot].fr=fr;e[tot].to=to;
    e[tot].nxt=head[fr];head[fr]=tot;
}

namespace Seg{
    #define ls x<<1
    #define rs x<<1|1
    void pushup(int x){
        sum[x]=sum[ls]+sum[rs];
    }
    
    void pushdown(int x,int ln,int rn){
        if(!lazy[x]) return;
        lazy[ls]^=1;
        lazy[rs]^=1;
        sum[ls]=ln-sum[ls];
        sum[rs]=rn-sum[rs];
        lazy[x]=0;
    }
    
    void build(int x,int l,int r){
        if(l==r){sum[x]=a[pre[l]];return;} 
        int mid=l+r>>1;
        build(ls,l,mid);build(rs,mid+1,r);
        pushup(x);
    }
    
    void update(int x,int l,int r,int L,int R){
        if(L<=l&&R>=r){sum[x]=r-l+1-sum[x],lazy[x]^=1;return;}
        int mid=l+r>>1;pushdown(x,mid-l+1,r-mid);
        if(L<=mid) update(ls,l,mid,L,R);
        if(R>=mid+1) update(rs,mid+1,r,L,R);
        pushup(x); 
    }
    
    int query(int x,int l,int r,int L,int R){
        if(L<=l&&R>=r)return sum[x];
        int mid=l+r>>1,ans=0;pushdown(x,mid-l+1,r-mid);
        if(L<=mid) ans+=query(ls,l,mid,L,R);
        if(R>=mid+1) ans+=query(rs,mid+1,r,L,R);
        return ans;
    }
}

namespace Cut{
    void dfs1(int x,int fat){
        dep[x]=dep[fat]+1;
        fa[x]=fat;siz[x]=1;
        for(int i=head[x];i;i=e[i].nxt){
            int to=e[i].to;
            if(to==fat) continue;
            dfs1(to,x);siz[x]+=siz[to];
            if(siz[to]>siz[son[x]])son[x]=to;
        }
    }
    
    void dfs2(int x,int tp){
        top[x]=tp;dfn[x]=++cnt;pre[cnt]=x;
        if(son[x]) dfs2(son[x],tp);
        for(int i=head[x];i;i=e[i].nxt){
            int to=e[i].to;
            if(to==fa[x]||to==son[x]) continue;
            dfs2(to,to);
        }
    }
}

int main(){
    n=read();
    for(int i=2,fa;i<=n;i++) fa=read(),add(fa,i);
    for(int i=1;i<=n;i++) a[i]=read();m=read();
    Cut::dfs1(1,0);Cut::dfs2(1,1);Seg::build(1,1,n);
    for(int i=1,pos;i<=m;i++){
        string opt;cin>>opt;pos=read();
        if(opt[0]=='g') printf("%d\n",Seg::query(1,1,n,dfn[pos],dfn[pos]+siz[pos]-1));
        else if(opt[0]=='p') Seg::update(1,1,n,dfn[pos],dfn[pos]+siz[pos]-1);
    }
    return 0;
}
posted @ 2021-04-25 16:43  KnightL  阅读(46)  评论(0编辑  收藏  举报