题意
你需要花(q)天时间将(n)位长的01字符串s变换成指定的01字符串t。在第(i)天,白天你会检查字符串的第(l_i)到(r_i)位(包含(l_i,r_i)),如果这些位置上不是全0或者全1,你就会不开心。晚上,你可以偷偷改变(l_i)到(r_i)上部分位置的字符,但改变的位置要严格小于[l_i,r_i]位置数的一半。问是否存在一种修改方式能保证你能将s变化到t且保证不出现不开心的情况。
数据范围
[1leq nleq 2 imes 10^5
]
[0leq qleq 2 imes 10^5
]
题解
这题顺着搞不好搞,但反过来异常好做。我们从字符串t变到字符串s,每天先改变区间([l_i,r_i])的字符再检查区间是否全0或全1,又因为每次只能修改少于半数的字符,所以修改的方式唯一,即如果区间1的个数少于一半则区间变为全0,如果区间内1的个数多于一般,则区间全变为0,如果区间0和1数目相等即均为一半则不能修改,直接输出NO。最后修改完之后,再判断修改过后的字符串是否为s。这里涉及到区间查询,区间修改,建一棵线段树就能搞定。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define LL long long
#define ls (node<<1)
#define rs (node<<1|1)
#define fi first
#define se second
#define pr pair<int,int>
#define mk(a,b) make_pair(a,b)
using namespace std;
int read(){
char x=getchar(); int u=0,fg=0;
while(!isdigit(x)){ if(x=='-') fg=1; x=getchar(); }
while(isdigit(x)){ u=(u<<3)+(u<<1)+(x^48); x=getchar(); }
return fg?-u:u;
}
const int maxx=2e5+10;
int tr[maxx<<3],sum[maxx<<3],lazy[maxx<<3];
char s[maxx],f[maxx];
pr ask[maxx];
void push_up(int node){
tr[node]=tr[ls]+tr[rs];
}
void push_down(int node,int l,int mid,int r){
if(!lazy[node]) return;
tr[ls]=(lazy[node]-1)*(mid-l+1);
tr[rs]=(lazy[node]-1)*(r-mid);
lazy[ls]=lazy[node];
lazy[rs]=lazy[node];
lazy[node]=0;
}
void build(int node,int l,int r){
lazy[node]=0;
if(l>=r){
tr[node]=(f[l]-'0');
// printf("%d
",f[l]-'0');
return ;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
push_up(node);
}
void update(int node,int l,int r,int ul,int ur,LL x){
if(ul<=l && ur>=r){
tr[node]=x*(r-l+1);
lazy[node]=x+1;
return;
}
int mid=(l+r)>>1;
push_down(node,l,mid,r);
if(ur<=mid) update(ls,l,mid,ul,ur,x);
else if(ul>mid) update(rs,mid+1,r,ul,ur,x);
else{
update(ls,l,mid,ul,mid,x);
update(rs,mid+1,r,mid+1,ur,x);
}
push_up(node);
}
LL query(int node,int l,int r,int ul,int ur){
if(ul<=l && ur>=r) return tr[node];
int mid=(l+r)>>1;
push_down(node,l,mid,r);
if(ur<=mid) return query(ls,l,mid,ul,ur);
else if(ul>mid) return query(rs,mid+1,r,ul,ur);
else return query(ls,l,mid,ul,mid)+query(rs,mid+1,r,mid+1,ur);
}
bool check(int node,int l,int r){
if(l>=r){
if(tr[node]==0 && s[l]=='0') return 1;
else if(tr[node]==1 && s[l]=='1') return 1;
else return 0;
}
int mid=(l+r)>>1;
push_down(node,l,mid,r);
return check(ls,l,mid)&check(rs,mid+1,r);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in", "r", stdin);
freopen("output.out", "w", stdout);
#endif
int T=read(),n,q;
while(T--){
n=read(); q=read();
scanf("%s",s+1);
scanf("%s",f+1);
build(1,1,n);
For(i,1,q){
int u=read(),v=read();
ask[i]=mk(u,v);
}
bool flag=1;
for(int i=q;i;--i){
int tmp=query(1,1,n,ask[i].fi,ask[i].se),len=ask[i].se-ask[i].fi+1;
// printf("%d
",tmp);
if(tmp*2<len) update(1,1,n,ask[i].fi,ask[i].se,0);
else if((len-tmp)*2<len) update(1,1,n,ask[i].fi,ask[i].se,1);
else{
flag=0;
break;
}
}
// cout<<flag<<endl;
if(flag) flag=check(1,1,n);
if(flag) printf("YES
");
else printf("NO
");
}
return 0;
}