P8271 [USACO22OPEN] COW Operations S

洛谷

蒟蒻给一个时间复杂度较劣的线段树做法。

我们可以发现两个字符处理的结果和处理的顺序没有关系,那么我们可以先考虑将每一部分都尝试合成一个或没有字符,再进行合并。

那么我们其实可以考虑使用线段树直接维护每个区间内经过合成剩下了什么,即可判断是否正确。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
char s[200005];
int merge(int a,int b){
	if(a==0)return b;
	if(b==0)return a;
	if(a==b)return 0;
	if(a==1&&b==2||a==2&&b==1)return 3;
	if(a==1&&b==3||a==3&&b==1)return 2;
	if(a==2&&b==3||a==3&&b==2)return 1;
}
struct ST{
	int c[800005];
	#define ls p<<1
	#define rs p<<1|1
	void pushup(int p){
		c[p]=merge(c[ls],c[rs]);
	}
	void build(int p,int l,int r){
		if(l==r){
			if(s[l]=='C')c[p]=1;
			else if(s[l]=='O')c[p]=2;
			else c[p]=3;
			return;
		}
		int mid=l+r>>1;
		build(ls,l,mid),build(rs,mid+1,r);
		pushup(p);
	}
	int query(int p,int l,int r,int L,int R){
		if(l>=L&&r<=R)return c[p];
		int mid=l+r>>1;
		if(mid>=L&&mid<R)return merge(query(ls,l,mid,L,R),query(rs,mid+1,r,L,R));
		if(mid>=L)return query(ls,l,mid,L,R);
		return query(rs,mid+1,r,L,R);
	}
}seg;
signed main(){
	cin>>s+1;
	int n=strlen(s+1);
	seg.build(1,1,n);
	int q;
	cin>>q;
	int l,r;
	while(q--){
		cin>>l>>r;
		int tmp=seg.query(1,1,n,l,r);
		if(tmp==1)cout<<"Y";
		else cout<<"N";
	}
	return 0;
}

posted @ 2025-12-07 13:01  huhangqi  阅读(4)  评论(0)    收藏  举报