苹果树

题面

题目描述

卡卡家门外有一棵苹果树。每年秋天,树上都会种很多苹果。卡卡非常喜欢苹果,因此他一直在精心培育大苹果树。

该树有 \(n\) 个分叉,这些分叉由树枝连接。卡卡用 \(1\)\(n\) 对分叉进行编号,并且根始终用 \(1\) 编号。在叉上将生长苹果,而在同一叉上将不会生长出两个苹果。卡卡想了解某个子树中有多少个苹果,以便研究苹果树的结果能力。

问题在于,有时候,一个空叉上会长出一个新苹果,或者卡卡可能会从树上摘下一个苹果作为甜点。你能帮卡卡吗?

输入格式

第一行包含一个整数 \(n\) ,代表分叉数量。

接下来 \(n−1\) 行分别包含两个整数 \(u,v\) ,意味着分支 \(u\) 和分支 \(v\) 通过一个树枝连接

下一行包含一个整数 \(m\)
接下来 \(m\) 行分别包含一个操作

C x,这代表着在分叉 \(x\) 上苹果的存在状态发生更改。也就是如果分叉上有一个苹果,则卡卡摘下;否则,空叉上会长出一个新苹果。

Q x,表示查询分叉 \(x\) 上方子树中的苹果数量,请注意,开始时树上结满了苹果

输出格式

对于每一个询问,输出一行一个答案

输入样例

3
1 2
1 3
3
Q 1
C 2
Q 1

输出样例

3
2

数据范围

\(1≤N,M≤100,000\)
\(1≤u,v≤n\)

题解:

看到这个询问方式,很容易联想到 线段树
对于树上问题,我们可以通过dfs序转换为区间问题。
那么代码就显而易见了:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int M=4e5+5;
struct edge{
	int to,nxt;
}e[M];
int head[M],sum[M],vis[M],in[M],out[M],n,q,cnt,res;
int ll[M], rr[M];
void add(int u,int v){
	e[++cnt]=(edge){v,head[u]};
	head[u]=cnt;
}
void dfs(int u){
	in[u]=++res;
	vis[u]=1;
    ll[u] = rr[u] = res;
	for(int i=head[u];i;i=e[i].nxt){
		if(vis[e[i].to])continue;
		dfs(e[i].to);
		ll[u] = min(ll[u], ll[e[i].to]);
		rr[u] = max(rr[u], rr[e[i].to]);
	}
	out[u]=res;
}
inline int read(){
	int x=0,f=1;
	char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=x*10+c-48;
		c=getchar();
	}
	return x*f;
}
void Build(int l,int r,int t){
	if(l==r){
		sum[t]=1;
		return;
	}
	int mid=l+r>>1;
	Build(l,mid,t<<1);
	Build(mid+1,r,t<<1|1);
	sum[t]=sum[t<<1]+sum[t<<1|1];
}
int que(int l,int r,int t,int x,int y){
	int ans = 0;
    if(l > y or r < x)	return 0;
	if(l>=x&&r<=y){
		ans+=sum[t];
		return ans;
	}
	int mid=l+r>>1;
	if(x<=mid) ans+=que(l,mid,t<<1,x,y);
	if(y>mid) ans += que(mid+1,r,t<<1|1,x,y);
	return ans;
} 
void change(int pos,int l,int r,int t){
	if(l==r){
		sum[t]=1-sum[t];
		return;
	}
	int mid=l+r>>1;
	if(pos<=mid) change(pos,l,mid,t<<1);
	else change(pos,mid+1,r,t<<1|1);
	sum[t]=sum[t<<1] + sum[t<<1|1];
}

signed main(){
	n=read();
	for(int i=1;i<n;i++){
		int u=read(),v=read();
		add(u,v);
		add(v,u);
	}
	Build(1,n,1);
	dfs(1);
	q=read();
	while(q--){ 
		char x=getchar();
		int u=read();
		if(x=='C')change(in[u],1,n,1);
		else printf("%lld\n",que(1,n,1,ll[u],rr[u]));
	}
    // system("PAUSE");
}
posted @ 2022-07-12 21:05  WRuperD  阅读(48)  评论(0编辑  收藏  举报

本文作者:DIVMonster

本文链接:https://www.cnblogs.com/guangzan/p/12886111.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

这是一条自定义内容

这是一条自定义内容