Codeforces Round #442 (Div. 2)E. Danil and a Part-time Job 线段树+lazytag

题意:一颗有根树,树上每一个节点有一个灯,要支持两种操作

第一种操作是统计一颗子树内开着的灯个数。

第二种操作是将一个子树内的所有灯状态改变(开灯->关灯,关灯->开灯)。

解:

经典处理方法是先把树通过dfs序拍成区间,预处理出每个结点u管理的左右端点

然后变成区间改变01状态,求和问题

01状态用lazy维护一下

#include<bits/stdc++.h>
#define ls (rt<<1)
#define rs (rt<<1|1)
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int maxn=2e5+5;
typedef long long ll;
int n,dfn[maxn],w[maxn],L[maxn],R[maxn];
void debug(int x){ cout<<": "<<x<<endl;}
struct seg{
    int l,r,len,sum,lazy;
    //
}t[maxn<<2];
void push_up(int rt){
    //
    t[rt].sum=t[ls].sum+t[rs].sum;
}
void push_down(int rt){
    //
    if(!t[rt].lazy) return;
    t[ls].lazy^=t[rt].lazy;
    t[ls].sum=t[ls].len-t[ls].sum;
    t[rs].lazy^=t[rt].lazy;
    t[rs].sum=t[rs].len-t[rs].sum;
    t[rt].lazy=0;// lazy==0 表示没有操作了 
}
void build(int rt,int l,int r){
    t[rt].l=l;t[rt].r=r;
    t[rt].len=r-l+1;
    t[rt].lazy==0;
    if(l==r){
       t[rt].sum=w[dfn[l]];
       return;
    }
    int mid=(l+r)>>1;
    build(ls,l,mid);build(rs,mid+1,r);
    push_up(rt);
}
void update(int rt,int l,int r){
    //cout<<rt<<" "<<l<<" "<<r<<endl;
    if(l<=t[rt].l&&t[rt].r<=r){
        // update
        t[rt].lazy^=1;
        t[rt].sum=t[rt].len-t[rt].sum;
        return;  
    }
    push_down(rt);
    if(t[ls].r>=l) update(ls,l,r);
    if(t[rs].l<=r) update(rs,l,r);
    push_up(rt);
}
int ask(int rt,int l,int r){
    //cout<<rt<<" "<<l<<" "<<r<<endl;
    if(l<=t[rt].l&&t[rt].r<=r){
        return t[rt].sum;//
    }
    push_down(rt);
    int ans=0;
    if(t[ls].r>=l) ans=(ans+ask(ls,l,r));//
    if(t[rs].l<=r) ans=(ans+ask(rs,l,r));//
    push_up(rt);
    return ans;
} 
int step;
vector<int>e[maxn];
void dfs(int u,int fa){
    ++step;
    dfn[step]=u;
    L[u]=step;
    for(int i=0;i<e[u].size();i++){
        int to=e[u][i];
        if(to==fa) continue;
        dfs(to,u);
    }
    R[u]=step;
    //cout<<u<<" "<<L[u]<<" "<<R[u]<<endl;
}
int main(){
    //freopen("lys.in","r",stdin);
    fastio;
    cin>>n;
    for(int i=2;i<=n;i++) {
        int x;cin>>x;
        e[x].push_back(i);
    }
    for(int i=1;i<=n;i++) cin>>w[i];
    dfs(1,0);
    build(1,1,n);
    int q;cin>>q;
    for(int i=1;i<=q;i++){
        string s;cin>>s;
        int v;cin>>v;
        //cout<<s<<" "<<v<<endl;
        if(s[0]=='p'){
            update(1,L[v],R[v]);
        }
        else {
            cout<<ask(1,L[v],R[v])<<endl;
        }
    }
}

一发过还是很爽的:)

posted @ 2023-02-14 12:44  liyishui  阅读(10)  评论(0编辑  收藏  举报