Codeforces Round #698 (Div. 2) E题 Nezzar and Binary String (线段树、逆向思维)
题意
你需要花\(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且保证不出现不开心的情况。
数据范围
\[1\leq n\leq 2\times 10^5
\]
\[0\leq q\leq 2\times 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\n",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\n",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\n");
else printf("NO\n");
}
return 0;
}

浙公网安备 33010602011771号