cunzai_zsy0531

关注我

P4979 矿洞:坍塌 题解

题面

开一棵线段树,区间内合并左右儿子的时候,如果颜色相同则赋成此颜色,否则直接赋成 \(0\),第三个操作只需要区间 \([l,r]\) 答案不为 \(0\) 且两边颜色不一样即可。比较简单,复杂度 \(O(n\log n)\)

点击查看代码
#include<iostream>
#include<cstdio>
using namespace std;
const int N=5e5+13;
int n,m;char in[N];
struct SegTree{int l,r,dat,set;}t[N<<2];
#define ls p<<1
#define rs p<<1|1
#define mid ((t[p].l+t[p].r)>>1)
inline void refresh(int p){t[p].dat=(t[ls].dat==t[rs].dat?t[ls].dat:0);}
void build(int p,int l,int r){
	t[p].l=l,t[p].r=r;
	if(l==r){t[p].dat=in[l]-'A'+1;return;}
	build(ls,l,mid),build(rs,mid+1,r);
	refresh(p);
}
inline void pushup(int p,int x){t[p].dat=t[p].set=x;}
inline void pushdown(int p){
	if(!t[p].set) return;
	pushup(ls,t[p].set),pushup(rs,t[p].set);
	t[p].set=0;
}
void update(int p,int l,int r,int x){
	if(l<=t[p].l&&t[p].r<=r) return pushup(p,x);
	pushdown(p);
	if(l<=mid) update(ls,l,r,x);
	if(r>mid) update(rs,l,r,x);
	refresh(p);
}
int query(int p,int l,int r){
	if(l<=t[p].l&&t[p].r<=r) return t[p].dat;
	pushdown(p);
	if(r<=mid) return query(ls,l,r);
	if(l>mid) return query(rs,l,r);
	int lc=query(ls,l,r),rc=query(rs,l,r);
	return lc==rc?lc:0;
}
#undef ls
#undef rs
#undef mid
int main(){
	scanf("%d%s",&n,in+1);
	build(1,1,n);
	scanf("%d",&m);
	while(m--){
		int l,r;char op,c;
		cin>>op;scanf("%d%d",&l,&r);
		if(op=='A') cin>>c,update(1,l,r,c-'A'+1);
		else puts(query(1,l,r)&&(l==1||r==n||query(1,l-1,l-1)!=query(1,r+1,r+1))?"Yes":"No");
	}
	return 0;
}
posted @ 2022-05-19 16:39  cunzai_zsy0531  阅读(23)  评论(0编辑  收藏  举报