当前位置:   article > 正文

Codeforces #698 (Div. 2) E. Nezzar and Binary String 题解

nezzar
中文题意:

T T T 组数据

给你两个长度为 n n n 的01串 s , f , s,f, s,f, q q q 次询问。

每次询问有区间 [   l , r   ] [\ l,r\ ] [ l,r ] ,如果 [   l , r   ] [\ l,r\ ] [ l,r ] 同时包含 0 0 0 1 1 1,则询问终止,否则你可以改变区间 [   l , r   ] [\ l,r\ ] [ l,r ] 内严格小于 l e n l r len_{lr} lenlr 的数字。

问是否可以使得询问不终止,且经过 q q q 次询问后可以将 s s s改为 f f f

前置知识:
线段树

没了

思路:

发现没法正序推过去(反正我不会),考虑根据询问逆推。

那么对于 f f f ,和 q 1 , q 2 q_{1},q_{2} q1,q2··· q n q_{n} qn ,用 l i , r i l_{i},r_{i} li,ri 来表示 q i q_{i} qi , s i s_{i} si表示经过前 i i i 次询问后的字符串 s s s

对于第 n n n 次询问,当且仅当 s n − 1 s_{n-1} sn1中的 [ l n , r n ] [l_{n},r_{n}] [ln,rn] 全为 k k k ( k k k ∈ \in ( 0 , 1 ) (0,1) (0,1) ) , f f f [ l n , r n ] [l_{n},r_{n}] [ln,rn] 内( k ⊕ 1 k\oplus 1 k1)的数量 n u m k ⊕ 1 num_{k\oplus 1} numk1 < < < l e n l r len_{lr} lenlr 时,

s n − 1 s_{n-1} sn1 可转化 f f f

因此,我们可以对于 f f f n n n 开始向前遍历询问。对于 [ l i , r i ] [l_{i},r_{i}] [li,ri] , 将 [ l i , r i ] [l_{i},r_{i}] [li,ri] 内数量较少的数字改为另一个数字。

显然,当 [ l i , r i ] [l_{i},r_{i}] [li,ri] n u m 1 = n u m 0 num_{1} = num_{0} num1=num0 时,询问会终止,因为改变量必须严格小于区间长度的一半。

遍历到最后判断 s s s 和经过转化的 f f f 是否相同就行了。

做法:

对于区间,查询和改变问题,我们可以用线段树在 l o g   n log\ n log n 的复杂度下解决。

首先对于 f f f 建立线段树,维护区间内 1 1 1 的数量。

对于区间修改,建立 l a z y lazy lazy 标记, − 1 -1 1 表示不变, 0 0 0 表示 l a z y lazy lazy 下的区间全为 0 0 0 1 1 1 表示 l a z y lazy lazy 下的区间全为 1 1 1

p u s d o w n pusdown pusdown 操作:

inline void pushdown(int p,int l,int r)
{
	if(laz[p]==-1)//未被标记跳过
		return ;
	int mid=(l+r)>>1;
	if(laz[p])//标记为1
	{
		tr[p<<1]=(mid-l+1);
		tr[p<<1|1]=(r-mid);
		laz[p<<1]=laz[p<<1|1]=1;
		laz[p]=-1;
		return ;
	}
	tr[p<<1]=tr[p<<1|1]=0;//标记为0
	laz[p<<1]=laz[p<<1|1]=0;
	laz[p]=-1;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

剩下的就是线段树的基本操作了。

Code:
#include<bits/stdc++.h>
#define N 240000
using namespace std;
 
int t,n,q;
char s[N],f[N];
int ql[N],qr[N],tr[N<<2],laz[N<<2];
 
inline int read()
{
	char a=0;int w=1,x=0;
	while(a<'0'||a>'9'){if(a=='-')w=-1;a=getchar();}
	while(a<='9'&&a>='0'){x=(x<<3)+(x<<1)+(a^48);a=getchar();}
	return x*w;
}
 
inline void pushdown(int p,int l,int r)
{
	if(laz[p]==-1)//未被标记跳过
		return ;
	int mid=(l+r)>>1;
	if(laz[p])//标记为1
	{
		tr[p<<1]=(mid-l+1);
		tr[p<<1|1]=(r-mid);
		laz[p<<1]=laz[p<<1|1]=1;
		laz[p]=-1;
		return ;
	}
	tr[p<<1]=tr[p<<1|1]=0;//标记为0
	laz[p<<1]=laz[p<<1|1]=0;
	laz[p]=-1;
}
 
void build(int p,int l,int r)//建树
{
	laz[p]=-1;
	if(l==r)
	{
		tr[p]=(f[l]^48);
		return ;
	}
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	tr[p]=tr[p<<1]+tr[p<<1|1];
}
 
int que(int p,int l,int r,int L,int R)//查询1的数量
{
	if(L<=l&&r<=R)
		return tr[p];
	pushdown(p,l,r);
	int mid=(l+r)>>1;
	int ans=0;
	if(mid>=L)
		ans+=que(p<<1,l,mid,L,R);
	if(mid<R)
		ans+=que(p<<1|1,mid+1,r,L,R);
	return ans;
}
 
void modify(int p,int l,int r,int L,int R,int opt)//区间修改
{
	if(L<=l&&r<=R)
	{
		tr[p]=opt*(r-l+1);
		laz[p]=opt;
		return ;
	}
	pushdown(p,l,r);
	int mid=(l+r)>>1;
	if(mid>=L)
		modify(p<<1,l,mid,L,R,opt);
	if(mid<R)
		modify(p<<1|1,mid+1,r,L,R,opt);
	tr[p]=tr[p<<1]+tr[p<<1|1];
}
 
int main()
{
	t=read();
	while(t--)
	{
		n=read();
		q=read();
		int flag=1;
		scanf("%s%s",(s+1),(f+1));
		for(register int i=1;i<=q;i++)
		{
			ql[i]=read();
			qr[i]=read();
		}
		build(1,1,n);
		for(register int i=q;i>=1;i--)
		{
			int len=qr[i]-ql[i]+1;//区间长度
			int num=que(1,1,n,ql[i],qr[i]);//查询区间内1的数量
			if( num==len-num )//区间内0的数量为 len-num , 0和1数量相同时不可能成立
			{
				flag=0;
				break;
			}
			modify(1,1,n,ql[i],qr[i],num>(len-num) );//区间修改
		}
		if(!flag)
		{
			printf("NO\n");
			continue;
		}
		for(register int i=1;i<=n;i++)
		{
			int num=que(1,1,n,i,i);//取出经过q次询问后f的第i位
			if(num!=(s[i]^48))//判断f和s是否相等,不相等退出
			{
				flag=0;
				break;
			}
		}
		if(!flag)
		{
			printf("NO\n");
			continue;
		}
		printf("YES\n");
	}
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/75393
推荐阅读
相关标签
  

闽ICP备14008679号