P4979 礦洞:坍塌 題解
阿新 • • 發佈:2022-05-19
開一棵線段樹,區間內合併左右兒子的時候,如果顏色相同則賦成此顏色,否則直接賦成 \(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; }