题目大意:两个01串,q个询问,每次询问给定lr,串1lr内所有位置全为0或1,否则NO,询问后可以对lr内严格小于一半区间的字符进行修改,问q次询问过后,串1能否变为串2。

题目链接

 

解题思路:逆转时间,串1变为串2变为串2变串1,这样的好处是,对于询问来说,可以先修改再保证区间全为0或1,接下来就模拟就好了,每次找区间内较少的字符,修改为另一个,最后比较一下修改后的串和串1是否相等就好了。这里注意是严格小于一半区间,所以当0和1数量相等时,NO。

 

  1 #include<stdio.h>
  2 #include<algorithm>
  3 using namespace std;
  4 
  5 const int maxn=2e5+5;
  6 int t,n,q,q1[maxn],q2[maxn];
  7 int tree[maxn<<2],l[maxn<<2],r[maxn<<2],lazy[maxn<<2];
  8 char s1[maxn],s2[maxn];
  9 int cnt=0;
 10 void build(int root,int ll,int rr){
 11     l[root]=ll;r[root]=rr;
 12     lazy[root]=-1;
 13     if(ll==rr){
 14         if(s2[++cnt]=='1') tree[root]=1;
 15         else tree[root]=0;
 16         return;
 17     }
 18     int mid=(ll+rr)/2;
 19     build(root<<1,ll,mid);
 20     build(root<<1|1,mid+1,rr);
 21     tree[root]=tree[root<<1]+tree[root<<1|1];
 22 }
 23 
 24 void push_down(int root){
 25     if(l[root]==r[root]) return ;
 26     lazy[root<<1]=lazy[root];
 27     lazy[root<<1|1]=lazy[root];
 28     if(lazy[root]){
 29         tree[root<<1]=r[root<<1]-l[root<<1]+1;
 30         tree[root<<1|1]=r[root<<1|1]-l[root<<1|1]+1;
 31     }else {
 32         tree[root<<1]=0;
 33         tree[root<<1|1]=0;
 34     }
 35     lazy[root]=-1;
 36 }
 37 
 38 void updata(int root,int ll,int rr,int tmp){
 39     if(l[root]>=ll&&r[root]<=rr){
 40         if(tmp)
 41             tree[root]=r[root]-l[root]+1;
 42         else tree[root]=0;
 43         lazy[root]=tmp;
 44         return ;
 45     }
 46     if(lazy[root]!=-1) push_down(root);
 47     int mid=(l[root]+r[root])/2;
 48     if(mid<ll){
 49         updata(root<<1|1,ll,rr,tmp);
 50     }else if(mid>=rr){
 51         updata(root<<1,ll,rr,tmp);
 52     }else {
 53         updata(root<<1,ll,rr,tmp);
 54         updata(root<<1|1,ll,rr,tmp);
 55     }
 56     tree[root]=tree[root<<1]+tree[root<<1|1];
 57 }
 58 
 59 int query(int root,int ll,int rr){
 60     if(ll<=l[root]&&rr>=r[root]){
 61         return tree[root];
 62     }
 63     if(lazy[root]==0||lazy[root]==1){
 64         push_down(root);
 65     }
 66     int mid=(l[root]+r[root])/2;
 67     if(mid<ll){
 68         return query(root<<1|1,ll,rr);
 69     } else if(mid>=rr){
 70         return query(root<<1,ll,rr);
 71     } else {
 72         return query(root<<1,ll,rr)+query(root<<1|1,ll,rr);
 73     }
 74 }
 75 
 76 int main()
 77 {
 78     scanf("%d",&t);
 79     while(t--){
 80         int flag=1;
 81         cnt=0;
 82         scanf("%d%d",&n,&q);
 83         scanf("%s%s",s1+1,s2+1);
 84         build(1,1,n);
 85         for(int i=q;i>=1;i--){
 86             scanf("%d %d",&q1[i],&q2[i]);
 87         }
 88         for(int i=1;i<=q;i++){
 89             int cnt1=query(1,min(q1[i],q2[i]),max(q1[i],q2[i]));
 90             int cnt2=abs(q1[i]-q2[i])+1-cnt1;
 91             if(cnt1==cnt2){
 92                 flag=0;
 93                 break;
 94             } else if(cnt1>cnt2){
 95                 updata(1,min(q1[i],q2[i]),max(q1[i],q2[i]),1);
 96             } else{
 97                 updata(1,min(q1[i],q2[i]),max(q1[i],q2[i]),0);
 98             }
 99         }
100         for(int i=1;i<=n;i++){
101             int tmp=query(1,i,i);
102             if(s1[i]-'0'!=tmp){
103                 flag=0;break;
104             }
105         }
106         if(flag){
107             printf("YES\n");
108         } else{
109             printf("NO\n");
110         }
111     }
112     return 0;
113 }
View Code

 

 posted on 2021-01-31 16:26  haianx  阅读(125)  评论(0编辑  收藏  举报