【题解】 CF1478E Nezzar and Binary String 线段树+时间逆序

Legend

Link ( extrm{to Codeforces}).

Editorial

觉得这个题很屑,来写个题解。

发现按时间逆序之后,等价于每次修改后要保证这个区间同色(正着做的话就不是同一个区间)。

因为一次只能修改小于 (frac{len}{2}) 个数字,所以一定是修改成数量比较多的那种数字。

所以直接用线段树打区间覆盖维护区间和就行了。

特别地,区间查询发现如果 01 数量相同则输出 NO。

特别地,如果最终状态不符合初始状态也是 NO。

复杂度 (O(q log n + n))

Code

#include <bits/stdc++.h>

#define debug(...) fprintf(stderr ,__VA_ARGS__)
#define __FILE(x)
	freopen(#x".in" ,"r" ,stdin);
	freopen(#x".out" ,"w" ,stdout)
#define LL long long

const int MX = 2e5 + 23;
const LL MOD = 998244353;

int read(){
	char k = getchar(); int x = 0;
	while(k < '0' || k > '9') k = getchar();
	while(k >= '0' && k <= '9') x = x * 10 + k - '0' ,k = getchar();
	return x;
}

int L[MX] ,R[MX] ,n ,q;
char st[MX] ,ed[MX];

struct node{
	int l ,r ,cov ,sum;
	node *lch ,*rch;
}*root;

void docov(node *x ,int v){
	x->cov = v;
	x->sum = v * (x->r - x->l + 1);
}
void pushup(node *x){x->sum = x->lch->sum + x->rch->sum;}
void pushdown(node *x){if(~x->cov) docov(x->lch ,x->cov) ,docov(x->rch ,x->cov) ,x->cov = -1;}

node *build(int l ,int r){
	node *x = new node; x->l = l ,x->r = r;
	x->cov = -1 ,x->sum = 0;
	if(l == r){
		x->sum = ed[l] == '1';
		x->lch = x->rch = nullptr;
	}
	else{
		int mid = (l + r) >> 1;
		x->lch = build(l ,mid);
		x->rch = build(mid + 1 ,r);
		pushup(x);
	}return x;
}

int query(node *x ,int l ,int r){
	if(l <= x->l && x->r <= r) return x->sum;
	pushdown(x); int ans = 0;
	if(l <= x->lch->r) ans += query(x->lch ,l ,r);
	if(r > x->lch->r) ans += query(x->rch ,l ,r);
	return ans;
}

void cover(node *x ,int l ,int r ,int v){
	if(l <= x->l && x->r <= r) return docov(x ,v);
	pushdown(x);
	if(l <= x->lch->r) cover(x->lch ,l ,r ,v);
	if(r > x->lch->r) cover(x->rch ,l ,r ,v);
	return pushup(x);
}

bool check(node *x){
	if(x->l == x->r) return x->sum == st[x->l] - '0';
	pushdown(x);
	return check(x->lch) && check(x->rch);
}

void solve(){
	n = read() ,q = read();
	scanf("%s" ,st + 1);
	scanf("%s" ,ed + 1);
	root = build(1 ,n);
	
	for(int i = 1 ; i <= q ; ++i){
		L[i] = read() ,R[i] = read();
	}
	
	for(int i = q ,one ,zero ; i ; --i){
		one = query(root ,L[i] ,R[i]);
		zero = R[i] - L[i] + 1 - one;
		if(one == zero){
			puts("NO");
			return;
		}
		cover(root ,L[i] ,R[i] ,one > zero);
	}
	puts(check(root) ? "YES" : "NO");
}

int main(){
	int T = read();
	for(int i = 1 ; i <= T ; ++i){
		solve();
	}
	return 0;
}
原文地址:https://www.cnblogs.com/imakf/p/14343362.html