CYJian家的礦塌了之後,就沒有經濟來源了(不要問我怎麼沒有存款)。於是,CYJian迫切地想要修復他家的礦。
CYJian家的礦共出產三種礦石,所以我們也只能用三種材料來修復他們家的礦。我們已知共有噸材料,每噸材料均爲三種材料中的一種,它們連成了一個串,如:
CYJian家對材料的要求非常嚴格,他每次會選擇一段連續區間的材料作爲修復的材料。因爲不合要求的材料會使得礦再次塌陷,砸死CYJian,所以這個連續區間的材料必須滿足一下個要求:
這段連續區間必須是同一種材料
這段連續區間的前一個材料與後一個材料必須不相同。
例如,有一段材料爲,則~ 區間的 和 ~ 區間的 均符合要求,而 ~ 區間的 不符合要求。
材料有靈性,所以材料會有變化。
現在有噸材料,個詢問。每個詢問是以下的種形式之一:
A x y op 表示替換材料,將 到 區間內的材料替換爲 , 爲三種材料字符中的一個。
B x y 表示是否詢問,即詢問到區間內的材料是否合法,合法輸出,不合法輸出。
注意:當或時,你的程序不需要判斷前後的情況,而只需要判斷區間內的情況.
礦洞:坍塌 題解
分析
首先,我們考慮使用線段樹。
我們發現
-
對於操作
lazy_tag
修改就好了
-
對於操作
- 看這一段是否所有字符都相同
- 如果 ,單點查詢第 和 這 個字符是否相同就行了
如何看一段內所有字符是否相同
這個東西確實有點難,我的做法是,雖然字符很多,但每個字符都是 A
、B
、C
中的一個,所以可以直接看這段字符是否全是 A
、B
或 C
。
開始線段樹
維護
綜上所述,我們可以開始寫題了。
我們需要維護幾個值:
-
lazy
這個應該不用我說了吧,有 個值- 表示
A
- 表示
B
- 表示
C
- 表示
-
s[3]
這個就是看這段字符是否全是A
、B
或C
。- 表示這段字符是否全是
A
- 表示這段字符是否全是
B
- 表示這段字符是否全是
C
- 表示這段字符是否全是
pushup
這一段區間是否全是 A
、B
或 C
,僅當左兒子和右兒子都全是 A
、B
或 C
。
for(register int i=1;i<=3;i++)t[num].s[i]=(t[ls].s[i]&&t[rs].s[i]);
邊界條件
對於 的情況, 的值是否爲 ,僅當這個字符是否是A
、B
、C
。
pushup
修改左子樹和右子樹
void pushdown(int num){
if(t[num].lazy==1)down1(ls),down1(rs);
if(t[num].lazy==2)down2(ls),down2(rs);
if(t[num].lazy==3)down3(ls),down3(rs);
t[num].lazy=0;
}
說說 怎麼寫
首先把 lazy_tag
的值賦一下,然後,將 設爲 ,其他都設爲 。
void down1(int num){
t[num].lazy=1;
t[num].s[1]=1;
t[num].s[2]=0;
t[num].s[3]=0;
}
void down2(int num){
t[num].lazy=2;
t[num].s[1]=0;
t[num].s[2]=1;
t[num].s[3]=0;
}
void down3(int num){
t[num].lazy=3;
t[num].s[1]=0;
t[num].s[2]=0;
t[num].s[3]=1;
}
修改
這個是板子誒,不講了
void change(int num){
if(L<=t[num].l&&t[num].r<=R){
if(S==1)down1(num);
if(S==2)down2(num);
if(S==3)down3(num);
return;
}pushdown(num);
if(t[ls].r>=L)change(ls);
if(t[rs].l<=R)change(rs);
pushup(num);
}
單點查詢
這個是板子誒,不講了
int query2(int num,int S){//S是要查詢的點
if(t[num].l==t[num].r){
for(int i=1;i<=3;i++)
if(t[num].s[i])return i;
}pushdown(num);
if(t[ls].r>=S)return query2(ls,S);
if(t[rs].l<=S)return query2(rs,S);
}
區間查詢
這個是板子誒,不講了
bool query1(int num,int f){
if(L<=t[num].l&&t[num].r<=R)return t[num].s[f];
pushdown(num);
if(t[ls].r<L)return query1(rs,f);
if(t[rs].l>R)return query1(ls,f);
return (query1(ls,f)&&query1(rs,f));
}
代碼
// Problem : P4979 礦洞:坍塌
// Contest : Luogu
// URL : https://www.luogu.com.cn/problem/P4979
// Memory Limit : 250 MB
// Time Limit : 1000 ms
// Powered by CP Editor (https://github.com/cpeditor/cpeditor)
#include <bits/stdc++.h>
#define ls num<<1
#define rs num<<1|1
using namespace std;
typedef long long ll;
template<typename T>inline void read(T &FF){
T RR=1;FF=0;char CH=getchar();
for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
FF*=RR;
}
const int MAXN=5e5+10;
int a[MAXN],L,R,S,n;
struct Line_Tree{
struct Tree{
int l,r,lazy;
bool s[3];
}t[MAXN<<2];
void pushup(int num){
for(int i=1;i<=3;i++)t[num].s[i]=(t[ls].s[i]&&t[rs].s[i]);
}
void down1(int num){
t[num].lazy=1;
t[num].s[1]=1;
t[num].s[2]=0;
t[num].s[3]=0;
}
void down2(int num){
t[num].lazy=2;
t[num].s[1]=0;
t[num].s[2]=1;
t[num].s[3]=0;
}
void down3(int num){
t[num].lazy=3;
t[num].s[1]=0;
t[num].s[2]=0;
t[num].s[3]=1;
}
void pushdown(int num){
if(t[num].lazy==1)down1(ls),down1(rs);
if(t[num].lazy==2)down2(ls),down2(rs);
if(t[num].lazy==3)down3(ls),down3(rs);
t[num].lazy=0;
}
void build(int num,int l,int r){
t[num].l=l;t[num].r=r;t[num].lazy=0;
if(l==r){
for(int i=1;i<=3;i++)t[num].s[i]=(a[l]==i);
return;
}int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(num);
}
void change(int num){
if(L<=t[num].l&&t[num].r<=R){
if(S==1)down1(num);
if(S==2)down2(num);
if(S==3)down3(num);
return;
}pushdown(num);
if(t[ls].r>=L)change(ls);
if(t[rs].l<=R)change(rs);
pushup(num);
}
bool query1(int num,int f){
if(L<=t[num].l&&t[num].r<=R)return t[num].s[f];
pushdown(num);
if(t[ls].r<L)return query1(rs,f);
if(t[rs].l>R)return query1(ls,f);
return (query1(ls,f)&&query1(rs,f));
}
int query2(int num,int S){
if(t[num].l==t[num].r){
for(int i=1;i<=3;i++)
if(t[num].s[i])return i;
}pushdown(num);
if(t[ls].r>=S)return query2(ls,S);
if(t[rs].l<=S)return query2(rs,S);
}
}T;
int init(){
read(n);
for(int i=1;i<=n;i++){
char ch=getchar();
for(;ch!='A'&&ch!='B'&&ch!='C';ch=getchar());
a[i]=ch-64;
}T.build(1,1,n);
return 0;
}
int work2(){
if(L==1||R==n){puts("Yes");return 0;}
if(T.query2(1,L-1)!=T.query2(1,R+1))puts("Yes");
else puts("No");
return 0;
}
int work(){
char ch=getchar();for(;ch!='A'&&ch!='B';ch=getchar());
if(ch=='A'){
read(L);read(R);ch=getchar();for(;ch!='A'&&ch!='B'&&ch!='C';ch=getchar());S=ch-64;
T.change(1);
}else{
read(L);read(R);
for(int i=1;i<=3;i++)
if(T.query1(1,i)){work2();return 0;}
puts("No");
}
return 0;
}
int main(){
init();
int T;read(T);
while(T--){work();}
return 0;
}