CF1478E Nezzar and Binary String
描述
有两个个长为n的 0-1 串 \(s,f\),有 q 次查询,每次查询一个区间 \([l,r]\),每次查询要求区间里的数全是 0 或者全是 1。每次查询后都可以修改 [l,r] 区间内严格小于区间长度的字符,问经过 n 次查询和修改后,是否满足 s 能转化到 f。
思路
逆序思考,最后一次查询后,[l,r] 区间内肯定全是 0 或 1。那么根据 f 我们可以知道前面一个未修改的状态,由此我们可以逆推到第一个字符串,判断其是否等于 s 即可,用线段树维护区间内 1 的个数,和区间赋值操作即可。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
struct Node{
int l,r;
int sum,lazy;
}tr[N*4];
char s[N],f[N];
void pushup(int u){
tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
}
void pushdown(int u){
if(tr[u].lazy){
int k=tr[u].lazy;
if(k==1){
tr[u<<1].sum=(tr[u<<1].r-tr[u<<1].l+1);
tr[u<<1|1].sum=(tr[u<<1|1].r-tr[u<<1|1].l+1);
}else{
tr[u<<1].sum=tr[u<<1|1].sum=0;
}
tr[u<<1].lazy=tr[u<<1|1].lazy=k;
}
tr[u].lazy=0;
}
void build(int u,int l,int r){
if(l==r) {
tr[u]={l,r,f[l]-'0',0};
}else{
int mid=l+r>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
pushup(u);
tr[u].l=l; tr[u].r=r;
tr[u].lazy=0;
}
}
void modify(int u,int l,int r,int d){
if(l<=tr[u].l && r>=tr[u].r) {
if(d==1){
tr[u].sum=tr[u].r-tr[u].l+1;
tr[u].lazy=1;
}else{
tr[u].sum=0;
tr[u].lazy=-1;
}
}else{
pushdown(u);
int mid=tr[u].l+tr[u].r>>1;
if(mid>=l) modify(u<<1,l,r,d);
if(mid+1<=r) modify(u<<1|1,l,r,d);
pushup(u);
}
}
int query(int u,int l,int r){
if(l<=tr[u].l && r>=tr[u].r) {
return tr[u].sum;
}else{
pushdown(u);
int mid=tr[u].l+tr[u].r>>1;
int sum=0;
if(mid>=l) sum=query(u<<1,l,r);
if(mid+1<=r) sum+=query(u<<1|1,l,r);
return sum;
}
}
bool check(int u){
int l=tr[u].l,r=tr[u].r;
if(l==r) {
return tr[u].sum==s[l]-'0';
}else{
pushdown(u);
return check(u<<1)&check(u<<1|1);
}
}
int main(){
int t; cin>>t; for(int x=1;x<=t;x++){
int n,q; scanf("%d%d%s%s",&n,&q,s+1,f+1);
build(1,1,n);
vector<array<int,2>> v(q);
for(int i=0;i<q;i++){
int l,r; scanf("%d%d",&l,&r);
v[i]={l,r};
}
bool flag=true;
for(int i=q-1;i>=0;i--){
int l=v[i][0],r=v[i][1];
int t=query(1,l,r);
int tt=r-l+1-t;
if(t==tt){flag=false; break;}
if(t<tt) modify(1,l,r,-1);
else modify(1,l,r,1);
}
if(flag) flag=check(1);
if(flag) puts("YES");
else puts("NO");
}
return 0;
}

浙公网安备 33010602011771号