CF877E
解题思路 DFS序 + 线段树
当看到这个题的时候,发现是一个树上问题且存在修改和询问,这个题有俩种操作
- 区间翻转
- 区间查询1的个数
很显然了线段树可以轻松维护这种信息,sum 记录区间1的个数,lzy懒标记。
由于查询的是树上问题 可以用DFS序从树上问题转换成线性问题,然后就可以线段树暴力硬屮了
具体细节看代码了
#include<bits/stdc++.h>
using namespace std;
// #define int long long
#define endl "\n"
#define x first
#define y second
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned long long ull;
const int N=1000010,M=1010,mod=998244353;
int a[N],m;
struct node{
int l,r,sum,lzy;
}tr[N];
int n,L[N],R[N],t,pos[N];
vector<int> e[N];
void dfs(int u)
{
L[u]=++t;
pos[t]=u;
for(auto j:e[u])
dfs(j);
R[u]=t;
}
void pushdown(int u)
{
int x=tr[u].lzy;
if(!x) return ;
tr[u<<1].lzy^=1;
tr[u<<1].sum=(tr[u<<1].r-tr[u<<1].l+1)-tr[u<<1].sum;
tr[u<<1|1].lzy^=1;
tr[u<<1|1].sum=(tr[u<<1|1].r-tr[u<<1|1].l+1)-tr[u<<1|1].sum;
tr[u].lzy=0;
}
void pushup(int u)
{
tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
}
void build(int u,int l,int r)
{
if(l==r)
{
int x=pos[l];
tr[u]={l,r,a[x],0};
return ;
}
tr[u]={l,r};
int mid=l+r>>1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
pushup(u);
}
void modify(int u,int l,int r)
{
if(tr[u].l>r||tr[u].r<l) return ;
if(tr[u].l>=l&&tr[u].r<=r)
{
tr[u].lzy^=1;
tr[u].sum=(tr[u].r-tr[u].l+1)-tr[u].sum;
return ;
}
pushdown(u);
int mid=tr[u].l+tr[u].r>>1;
if(mid>=l) modify(u<<1,l,r);
if(r>mid) modify(u<<1|1,l,r);
pushup(u);
}
int query(int u,int l,int r)
{
if(tr[u].l>r||tr[u].r<l) return 0;
if(tr[u].l>=l&&tr[u].r<=r) return tr[u].sum;
pushdown(u);
int mid=tr[u].l+tr[u].r>>1;
int ans=0;
if(mid>=l) ans+=query(u<<1,l,r);
if(r>mid) ans+=query(u<<1|1,l,r);
return ans;
}
void solve()
{
cin >> n;
for(int i=2;i<=n;i++)
{
int x;
cin >> x;
e[x].push_back(i);
}
dfs(1);
for(int i=1;i<=n;i++) cin >> a[i];
build(1,1,n);
cin >> m;
while(m--)
{
string op;
int v;
cin >> op >> v;
if(op=="get") cout << query(1,L[v],R[v]) << endl;
else modify(1,L[v],R[v]);
}
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T=1;
while(T--) solve();
return 0;
}