Codeforces Round #698 (Div. 1) B. Nezzar and Binary String (线段树)

该博客讨论了Codeforces Round #698 (Div. 1) B问题,即如何在Nanako检查二进制字符串期间避免其不悦,并在限定天数内将字符串改为指定的二进制字符串。文章介绍了解决方案,使用线段树来维护区间,从目标字符串开始逆向推导,判断操作可行性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:https://codeforces.com/contest/1477/problem/B

B. Nezzar and Binary String

time limit per test

2 seconds

memory limit per test

512 megabytes

input

standard input

output

standard output

Nezzar has a binary string ss of length nn that he wants to share with his best friend, Nanako. Nanako will spend qq days inspecting the binary string. At the same time, Nezzar wants to change the string ss into string ff during these qq days, because it looks better.

It is known that Nanako loves consistency so much. On the ii-th day, Nanako will inspect a segment of string ss from position lili to position riri inclusive. If the segment contains both characters '0' and '1', Nanako becomes unhappy and throws away the string.

After this inspection, at the ii-th night, Nezzar can secretly change strictly less than half of the characters in the segment from lili to riri inclusive, otherwise the change will be too obvious.

Now Nezzar wonders, if it is possible to avoid Nanako being unhappy and at the same time have the string become equal to the string ff at the end of these qq days and nights.

Input

The first line contains a single integer tt (1≤t≤2⋅1051≤t≤2⋅105) — the number of test cases.

The first line of each test case contains two integers n,qn,q (1≤n≤2⋅1051≤n≤2⋅105, 0≤q≤2⋅1050≤q≤2⋅105).

The second line of each test case contains a binary string ss of length nn.

The third line of each test case contains a binary string ff of length nn.

Then qq lines follow, ii-th of them contains two integers li,rili,ri (1≤li≤ri≤n1≤li≤ri≤n)  — bounds of the segment, that Nanako will inspect on the ii-th day.

It is guaranteed that the sum of nn for all test cases doesn't exceed 2⋅1052⋅105, and the sum of qq for all test cases doesn't exceed 2⋅1052⋅105.

Output

For each test case, print "YES" on the single line if it is possible to avoid Nanako being unhappy and have the string ff at the end of qq days and nights. Otherwise, print "NO".

You can print each letter in any case (upper or lower).

Example

input

Copy

4
5 2
00000
00111
1 5
1 3
2 1
00
01
1 2
10 6
1111111111
0110001110
1 10
5 9
7 10
1 7
3 5
6 10
5 2
10000
11000
2 5
1 3

output

Copy

YES
NO
YES
NO

Note

In the first test case, 00000––––––→000––––11→0011100000_→000_11→00111 is one of the possible sequences of string changes.

In the second test case, it can be shown that it is impossible to have the string ff at the end.

题目大意:输入一个长度为n(1<=n<=2*10^{5})的01字符串s1,有q天,每一天的白天都需要检查字符串的区间[l_{i},r_{i}]是否为全0或者全1,晚上可以修改区间[l_{i},r_{i}]严格小于一半的字符。要求每天白天都通过检查,并且最后变为目标串s2是否可行。

题解:若从初始串s1开始推导,某一天可以进行多种可能的操作,而且对后面有很大的影响,很难进行推导和判断。但是如果我们反过来,从目标串s2开始,从最后一天开始往前推导,对于每一天的区间[l_{i},r_{i}],由于只能修改小于一半的字符,我们要么只能修改为全1,要么只能修改为全0,要么要修改刚好一半的字符这时就不能成功。每一天的操作都是固定的,推到第一天后判断和初始串是否相同就行了。对于每一天的操作要么把区间覆盖为全0,要么覆盖为全1。我们可以用线段树来进行维护。

复杂度n*logn

代码如下:

#include<bits/stdc++.h>

using namespace std;
const int nn =210000;
const int inff = 0x3fffffff;
const double eps = 1e-8;
typedef long long LL;
const double pi = acos(-1.0);
const LL mod = (479 << 21) + 1;
string s;
string targetS;
int tl[nn*20],tr[nn*20],sum[nn*20],lz[nn*20];
int n,q;
void build(int i,int l,int r)
{
    tl[i] = l;
    tr[i] = r;
    lz[i] = -1;
    if(l==r)
    {
        sum[i] = targetS[l-1]-'0';
        return;
    }
    int mid = (l+r)/2;
    build(i*2,l,mid);
    build(i*2+1,mid+1,r);
    sum[i] = sum[2*i]+sum[2*i+1];
}
void push_down(int i)
{
    if(lz[i]!=-1)
    {
        lz[2*i]=lz[2*i+1]=lz[i];
        sum[2*i] = lz[i]*(tr[2*i]-tl[2*i]+1);
        sum[2*i+1] = lz[i]*(tr[2*i+1]-tl[2*i+1]+1);
        lz[i]=-1;
    }
}
int Sum(int i,int l,int r)
{
    if(tl[i]>=l&&tr[i]<=r)
    {
        return sum[i];
    }
    push_down(i);
    int ret=0;
    int mid = (tl[i]+tr[i])/2;
    if(l<=mid)
        ret += Sum(i*2,l,r);
    if(r>mid)
        ret += Sum(i*2+1,l,r);
    return ret;
}
void Change(int i,int l,int r,int value)
{
    if(tl[i]>=l&&tr[i]<=r)
    {
        sum[i]=value*(tr[i]-tl[i]+1);
        lz[i]=value;
        return;
    }
    push_down(i);
    int mid = (tl[i]+tr[i])/2;
    if(l<=mid)
        Change(i*2,l,r,value);
    if(r>mid)
        Change(i*2+1,l,r,value);
    sum[i] = sum[2*i]+sum[2*i+1];
}
int inputL[nn],inputR[nn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>q;
        cin>>s;
        cin>>targetS;
        build(1,1,n);
        bool ans =true;
        for(int i=0;i<q;i++)
        {
            cin>>inputL[i]>>inputR[i];
        }
        for(int i=q-1;i>=0;i--)
        {
            int sumlr = Sum(1,inputL[i],inputR[i]);
            if(sumlr*2>(inputR[i]-inputL[i]+1))
            {
                Change(1,inputL[i],inputR[i],1);
            } else if(sumlr*2<(inputR[i]-inputL[i]+1)) {
                Change(1,inputL[i],inputR[i],0);
            } else {
                ans = false;
            }
        }
        if(ans) {
            for(int i=0;i<n;i++)
            {
                if(Sum(1,i+1,i+1)!=s[i]-'0')
                {
                    ans = false;
                    break;
                }
            }
        }
        if(ans)
        {
            puts("YES");
        }else{
            puts("NO");
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值