877E - Danil and a Part-time Job

877E - Danil and a Part-time Job
给一颗树,结点有权值,更新子树所有结点,查询结点子树的和;


思路参考我上一篇文章

转换完之后就是区间更新和查询,然后更新sum就是把开关的房间调换一下;
更新add值就用对2取余,不能用异或~~(刚开始想着用异或1,后来发现,add的值会超过1)
代码(

注意main() 函数里    A[L[i]]=a; 调试了无数次才发现是这里的问题
因为把结点按照DFS序重新编号后,L[i]才是线段树维护序列的下标;

#include <iostream>
#include <cstdio>
#include <vector>
#include<cstring>
#define mem(x) memset(x,0,sizeof(x))
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
using namespace std;
const int N=200010;

vector<int> G[N];
int sum[N<<2],L[N],R[N],A[N],add[N<<2];
int fa[N];
int vv=0;
void init(int n)
{
    for(int i=1;i<N;i++)
        G[i].clear();
    mem(sum);
    mem(L);
    mem(R);
    mem(add);
    mem(fa);
    vv=0;
}

void dfs(int u)
{
    vv++;
    L[u]=vv;
    for(int i=0;i<G[u].size();i++)
    {
        int v=G[u][i];
        if(v!=fa[u])dfs(v);
    }
    R[u]=vv;
}

void pu(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];}
void pd(int rt,int ln,int rn)
{
    if(add[rt]){
        add[rt<<1]=(add[rt]+add[rt<<1])%2;
        add[rt<<1|1]=(add[rt]+add[rt<<1|1])%2;
        //cout<<"add[3]="<<add[3]<<endl;
        //cout<<"add[rt]="<<add[rt]<<endl;
        //cout<<"add[rt|1]="<<add[rt<<1|1]<<endl;
        //cout<<"pd-add-->";for(int i=1;i<=7;i++)cout<<add[i]<<' ';cout<<endl;
        //if((rt<<1|1)==3){cout<<add[rt]<<' '<<add[rt<<1|1]<<' '<<(add[rt]+add[rt<<1|1])%2<<endl;}
        sum[rt<<1]=ln-sum[rt<<1];
        sum[rt<<1|1]=rn-sum[rt<<1|1];
        add[rt]=0;
    }
}

void build(int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]=A[l];
        return ;
    }
    int m=(l+r)>>1;
    build(ls);build(rs);
    pu(rt);
}

void update(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        sum[rt]=(r-l+1)-sum[rt];
        add[rt]=(add[rt]+1)%2;
        return ;
    }
    int m=(l+r)>>1;
    pd(rt,m-l+1,r-m);
    if(L<=m)update(L,R,ls);
    if(R>m)update(L,R,rs);
    pu(rt);
}

int query(int L,int R,int l,int r,int rt)
{
    //cout<<"add-->";for(int i=1;i<=20;i++)cout<<add[i]<<' ';cout<<endl;
    //cout<<"sum-->";for(int i=1;i<=20;i++)cout<<sum[i]<<' ';cout<<endl;
    if(L<=l&&r<=R)
    {
        return sum[rt];
    }
    int m=(l+r)>>1;
    pd(rt,m-l+1,r-m);
    int ans=0;
    if(L<=m)ans+=query(L,R,ls);
    if(R>m)ans+=query(L,R,rs);
    pu(rt);
    return ans;
}

int main()
{
    int n,m;
    while(~scanf("%d",&n))
    {
        int a;
        init(n);
        for(int i=2;i<=n;i++)
        {
            scanf("%d",&a);
            fa[i]=a;
            //G[i].push_back(a);
            G[a].push_back(i);
        }
        dfs(1);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a);
            A[L[i]]=a;
        }
        //cout<<"L[2]="<<L[2]<<' '<<"R[2]"<<R[2]<<endl;
        build(1,n,1);
        scanf("%d",&m);
        char op[8];int x;
        for(int i=1;i<=m;i++)
        {
            scanf("%s%d",op,&x);
            if(op[0]=='g')cout<<query(L[x],R[x],1,n,1)<<endl;
            else update(L[x],R[x],1,n,1);
        }
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/zhonglong_lin/article/details/78634523
job