题解:P4979

题面

P4979

![[../../题面/洛谷题面/P4979|P4979]]

分析

裸区间推平,裸区间判同,珂朵莉树和线段树+lazytag均可。

线段树细节较多,谨慎处理

珂朵莉需在判同的时候,顺便进行合并,否则被 hack

代码

线段树


珂朵莉

#include <bits/stdc++.h>
#define IT set<node>::iterator
using namespace std;
const int N=1e6+1;
inline int read(){
    int x=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')(ch=='-')&&(w=-1,0),ch=getchar();
    while(ch>='0'&&ch<='9')x=(x*10)+(ch^48),ch=getchar();
    return x*w;
} 
inline void wrt(int x){
    if(x<0)putchar('-'),x=-x;
    if(x>9)wrt(x/10);
    putchar(x%10^48);
}
inline char getc(){
    char ch=getchar();
    while(ch!='A'&&ch!='B'&&ch!='C')ch=getchar();
    return ch;
}
struct node{
    int l,r;
    mutable char v;
    bool operator<(const node& o)const{return l<o.l;}
};
set<node>odt;
int n,m,l,r,cnt=1;
char str[N],lst,op;
IT itl,itr,tmp,it;
IT split(int pos){
    if(pos>n)return odt.end();
    it=odt.lower_bound({pos,0,0});
    if(it!=odt.end()&&it->l==pos)return it;
    --it;
    if(it->r<pos)return odt.end();
    int L=it->l,R =it->r;
    char V=it->v;
    odt.erase(it);
    odt.insert({L,pos-1,V});
    return odt.insert({pos,R,V}).first;
}
void assign(int l,int r,char v){
    itr=split(r+1),itl=split(l);
    odt.erase(itl,itr);
    odt.insert(node{l,r,v});
}
char ask(int pos){return split(pos)->v;}
bool check(int l,int r){
    itr=split(r+1),itl=split(l);
	tmp=itl;
    for(;itl!=itr;++itl)if(itl->v!=tmp->v)return 0;
    return 1;
}
int main(){
    n=read(),scanf("%s",str+1),lst=str[1];
    
    for(int i=1;i<=n;++i){
        if(str[i]==lst)++cnt;
		else odt.insert(node{i-cnt,i-1,lst}),lst=str[i],cnt=1;
    }
    odt.insert(node{n+1-cnt,n,lst});
    
	m=read();
    while(m--){
        op=getc(),l=read(),r=read();
        if(op=='A')assign(l,r,getc());
        else{
        	if(!check(l,r))puts("No");
        	else{
        		if(l==1||r==n||ask(r+1)!=ask(l-1))puts("Yes");
        		else puts("No");
			}
			assign(tmp->l,(--itl)->r,tmp->v);//for hack
        }
    }
    return 0;
}
posted @ 2025-08-20 20:55  badn  阅读(5)  评论(0)    收藏  举报