CF-877-E-dfs序+线段树

877-E 题目大意

给定一颗n个节点的树,根为1,点带权,权值要么为0,要么为1。

q次询问,两种类型:

  • get x:询问x的子树中有多少个1
  • pow x:将x子树中所有的值取反。

Solution

dfs序+线段树模板题,把子树上的操作转化为区间上的操作。

时间复杂度:O(nlogn)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=2e5+10;
struct node{
	int l,r;
	int sum,tag;
}tr[N<<2];

void pushup(int u){
	tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
}

void pushdown(int u){
	if(tr[u].tag){
		tr[u<<1].tag^=1;
		tr[u<<1].sum=tr[u<<1].r-tr[u<<1].l+1-tr[u<<1].sum;
		tr[u<<1|1].tag^=1;
		tr[u<<1|1].sum=tr[u<<1|1].r-tr[u<<1|1].l+1-tr[u<<1|1].sum;
		tr[u].tag=0;
	}
}

void build(int u,int l,int r){
	tr[u]={l,r,0,0};
	if(l==r) return;
	int m=(l+r)>>1;
	build(u<<1,l,m);
	build(u<<1|1,m+1,r);
}

void modify(int u,int l,int r){
	if(l<=tr[u].l&&tr[u].r<=r){
		tr[u].sum=tr[u].r-tr[u].l+1-tr[u].sum;
		tr[u].tag^=1;
		return;
	}
	pushdown(u);
	int m=(tr[u].l+tr[u].r)>>1;
	if(l<=m) modify(u<<1,l,r);
	if(r>m) modify(u<<1|1,l,r);
	pushup(u);
}

int query(int u,int l,int r){
	if(l<=tr[u].l&&tr[u].r<=r){
		return tr[u].sum;
	}
	pushdown(u);
	int m=(tr[u].l+tr[u].r)>>1;
	int res=0;
	if(l<=m) res+=query(u<<1,l,r);
	if(r>m) res+=query(u<<1|1,l,r);
	return res;
}

int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int n;
	cin>>n;
	vector<vector<int>> e(n);
	vector<int> L(n),R(n);
	int dfn=0;
	for(int i=1;i<n;i++){
		int p;
		cin>>p;
		p--;
		e[p].push_back(i);
	}
	function<void(int)> dfs=[&](int x){
		L[x]=++dfn;
		for(auto y:e[x]){
			dfs(y);
		}
		R[x]=dfn;
	};
	dfs(0);
	build(1,1,n);
	for(int i=0;i<n;i++){
		int w;
		cin>>w;
		if(w) modify(1,L[i],L[i]);
	}
	int q;
	cin>>q;
	while(q--){
		string op;
		int x;
		cin>>op>>x;
		x--;
		if(op=="get"){
			cout<<query(1,L[x],R[x])<<'\n';
		}else{
			modify(1,L[x],R[x]);
		}
	}
	return 0;
}
posted @   fengxue-K  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示