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且保证不出现不开心的情况。

数据范围

[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;
}
原文地址:https://www.cnblogs.com/Knowledge-Pig/p/14350961.html