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; } } }
一发过还是很爽的:)