题意:五种操作,0全部置0,1全部置1,2是0变1 1变0,3是询问1的个数,4是询问最长连续的1
思路:推荐先写hdu 3911 ,是这题的简单版,这题注意的地方就是一旦有置0和置1操作,那么2操作的标记就要被覆盖,剩下的操作都是比较精典的区间合并操作了
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=100010;
int num[maxn];
int cnt[maxn<<2],cnt0[maxn<<2],L[maxn<<2],R[maxn<<2],L0[maxn<<2],R0[maxn<<2],rev[maxn<<2];
int sum[maxn<<2],flag[maxn<<2];
void pushup(int node,int m){
sum[node]=sum[node<<1]+sum[node<<1|1];
L[node]=L[node<<1];R[node]=R[node<<1|1];
if(L[node]==m-(m>>1)) L[node]+=L[node<<1|1];
if(R[node]==m>>1) R[node]+=R[node<<1];
cnt[node]=max(L[node<<1|1]+R[node<<1],max(cnt[node<<1],cnt[node<<1|1]));
L0[node]=L0[node<<1];R0[node]=R0[node<<1|1];
if(L0[node]==m-(m>>1)) L0[node]+=L0[node<<1|1];
if(R0[node]==m>>1) R0[node]+=R0[node<<1];
cnt0[node]=max(L0[node<<1|1]+R0[node<<1],max(cnt0[node<<1],cnt0[node<<1|1]));
}
void pushdown(int node,int m){
if(flag[node]!=-1){
flag[node<<1]=flag[node<<1|1]=flag[node];
rev[node<<1]=rev[node<<1|1]=0;
if(flag[node]==0){
L0[node<<1]=R0[node<<1]=cnt0[node<<1]=m-(m>>1);
L[node<<1]=R[node<<1]=cnt[node<<1]=sum[node<<1]=0;
L0[node<<1|1]=R0[node<<1|1]=cnt0[node<<1|1]=m>>1;
L[node<<1|1]=R[node<<1|1]=cnt[node<<1|1]=sum[node<<1|1]=0;
}else{
L0[node<<1]=R0[node<<1]=cnt0[node<<1]=0;
L[node<<1]=R[node<<1]=cnt[node<<1]=sum[node<<1]=m-(m>>1);
L0[node<<1|1]=R0[node<<1|1]=cnt0[node<<1|1]=0;
L[node<<1|1]=R[node<<1|1]=cnt[node<<1|1]=sum[node<<1|1]=m>>1;
}
flag[node]=-1;
}
if(rev[node]){
rev[node<<1]^=1;rev[node<<1|1]^=1;
swap(L[node<<1],L0[node<<1]);
swap(R[node<<1],R0[node<<1]);
swap(cnt[node<<1],cnt0[node<<1]);
swap(L[node<<1|1],L0[node<<1|1]);
swap(R[node<<1|1],R0[node<<1|1]);
swap(cnt[node<<1|1],cnt0[node<<1|1]);
sum[node<<1]=m-(m>>1)-sum[node<<1];
sum[node<<1|1]=(m>>1)-sum[node<<1|1];
rev[node]=0;
}
}
void buildtree(int le,int ri,int node){
rev[node]=0;flag[node]=-1;
if(le==ri){
L[node]=R[node]=cnt[node]=sum[node]=num[le];
L0[node]=R0[node]=cnt0[node]=num[le]^1;
return ;
}
int t=(le+ri)>>1;
buildtree(le,t,node<<1);
buildtree(t+1,ri,node<<1|1);
pushup(node,ri-le+1);
}
void update(int l,int r,int val,int le,int ri,int node){
if(l<=le&&ri<=r){
if(val==0){
L0[node]=R0[node]=cnt0[node]=ri-le+1;
L[node]=R[node]=cnt[node]=sum[node]=0;
}else{
L0[node]=R0[node]=cnt0[node]=0;
L[node]=R[node]=cnt[node]=sum[node]=ri-le+1;
}
flag[node]=val;rev[node]=0;
return ;
}
pushdown(node,ri-le+1);
int t=(le+ri)>>1;
if(l<=t) update(l,r,val,le,t,node<<1);
if(r>t) update(l,r,val,t+1,ri,node<<1|1);
pushup(node,ri-le+1);
}
void update_rev(int l,int r,int le,int ri,int node){
if(l<=le&&ri<=r){
swap(L[node],L0[node]);
swap(R[node],R0[node]);
swap(cnt[node],cnt0[node]);
sum[node]=ri-le+1-sum[node];
rev[node]^=1;
return ;
}
pushdown(node,ri-le+1);
int t=(le+ri)>>1;
if(l<=t) update_rev(l,r,le,t,node<<1);
if(r>t) update_rev(l,r,t+1,ri,node<<1|1);
pushup(node,ri-le+1);
}
int query_sum(int l,int r,int le,int ri,int node){
if(l<=le&&ri<=r) return sum[node];
pushdown(node,ri-le+1);
int t=(le+ri)>>1,ans=0;
if(l<=t) ans+=query_sum(l,r,le,t,node<<1);
if(r>t) ans+=query_sum(l,r,t+1,ri,node<<1|1);
return ans;
}
int query_lcs(int l,int r,int le,int ri,int node){
if(l<=le&&ri<=r) return cnt[node];
pushdown(node,ri-le+1);
int t=(le+ri)>>1,ans=0;
if(l<=t) ans=max(ans,query_lcs(l,r,le,t,node<<1));
if(r>t) ans=max(ans,query_lcs(l,r,t+1,ri,node<<1|1));
ans=max(ans,min(R[node<<1],t-l+1)+min(L[node<<1|1],r-t));
return ans;
}
int main(){
int T,n,m,op,a,b;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&num[i]);
buildtree(1,n,1);
while(m--){
scanf("%d%d%d",&op,&a,&b);
a++;b++;
if(op==0) update(a,b,0,1,n,1);
if(op==1) update(a,b,1,1,n,1);
if(op==2) update_rev(a,b,1,n,1);
if(op==3) printf("%d\n",query_sum(a,b,1,n,1));
if(op==4) printf("%d\n",query_lcs(a,b,1,n,1));
}
}
return 0;
}