这题写着真累,⊙﹏⊙b汗
各种操作,具体见注释
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <climits>
#include <string>
#include <iostream>
#include <map>
#include <cstdlib>
#include <list>
#include <set>
#include <queue>
#include <stack>
using namespace std;
#define INF 0xfffffff
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 100010
int unsum[maxn<<2],sum[maxn<<2],lsum[maxn<<2],rsum[maxn<<2],zsum[maxn<<2],lzsum[maxn<<2],rzsum[maxn<<2],col[maxn<<2];
//unsum存储1的个数,sum存储连续的1,zsun存储连续的0
void pushup(int rt,int m)//向上更新
{
unsum[rt]=unsum[rt<<1]+unsum[rt<<1|1];
lsum[rt]=lsum[rt<<1];
rsum[rt]=rsum[rt<<1|1];
if(lsum[rt]==(m-(m>>1))) lsum[rt]+=lsum[rt<<1|1];
if(rsum[rt]==(m>>1)) rsum[rt]+=rsum[rt<<1];
sum[rt]=max(max(sum[rt<<1],sum[rt<<1|1]),rsum[rt<<1]+lsum[rt<<1|1]);
lzsum[rt]=lzsum[rt<<1];
rzsum[rt]=rzsum[rt<<1|1];
if(lzsum[rt]==(m-(m>>1))) lzsum[rt]+=lzsum[rt<<1|1];
if(rzsum[rt]==(m>>1)) rzsum[rt]+=rzsum[rt<<1];
zsum[rt]=max(max(zsum[rt<<1],zsum[rt<<1|1]),rzsum[rt<<1]+lzsum[rt<<1|1]);
}
void SWAP(int rt,int m)//交换操作,似的区间内0和1交换
{
col[rt]=1-col[rt];
unsum[rt]=m-unsum[rt];
swap(sum[rt],zsum[rt]);
swap(lsum[rt],lzsum[rt]);
swap(rsum[rt],rzsum[rt]);
}
void pushdown(int rt,int m)//向下更新
{
if(col[rt]==2)
{
col[rt]=-1;
SWAP(rt<<1,m-(m>>1));
SWAP(rt<<1|1,m>>1);
}
if(col[rt]!=-1)
{
col[rt<<1]=col[rt<<1|1]=col[rt];
unsum[rt<<1]=sum[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=col[rt<<1]?(m-(m>>1)):0;
unsum[rt<<1|1]=sum[rt<<1|1]=lsum[rt<<1|1]=rsum[rt<<1|1]=col[rt<<1|1]?(m>>1):0;
zsum[rt<<1]=lzsum[rt<<1]=rzsum[rt<<1]=col[rt<<1]?0:(m-(m>>1));
zsum[rt<<1|1]=lzsum[rt<<1|1]=rzsum[rt<<1|1]=col[rt<<1|1]?0:(m>>1);
col[rt]=-1;
}
}
void build(int l,int r,int rt)
{
col[rt]=-1;
if(l==r)
{
scanf("%d",&sum[rt]);
unsum[rt]=lsum[rt]=rsum[rt]=sum[rt];
zsum[rt]=lzsum[rt]=rzsum[rt]=sum[rt]^1;
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt,r-l+1);
}
void update(int L,int R,int add,int l,int r,int rt)
{
if(L<=l&&R>=r)
{
if(add==2)
{
SWAP(rt,r-l+1);
}
else
{
col[rt]=add;
unsum[rt]=sum[rt]=lsum[rt]=rsum[rt]=add?r-l+1:0;
zsum[rt]=lzsum[rt]=rzsum[rt]=add?0:r-l+1;
}
return ;
}
pushdown(rt,r-l+1);
int m=(l+r)>>1;
if(L<=m) update(L,R,add,lson);
if(R>m) update(L,R,add,rson);
pushup(rt,r-l+1);
}
int query(int L,int R,int add,int l,int r,int rt)//查询操作
{
int ans=0,m=(l+r)>>1;
if(add==3)
{
if(L<=l&&R>=r)
{
return unsum[rt];
}
pushdown(rt,r-l+1);
if(L<=m) ans+=query(L,R,add,lson);
if(R>m) ans+=query(L,R,add,rson);
return ans;
}
if(L<=l&&R>=r)
{
return sum[rt];
}
pushdown(rt,r-l+1);
ans=min(m-L+1,rsum[rt<<1])+min(lsum[rt<<1|1],R-m);
if(L<=m) ans=max(ans,query(L,R,add,lson));
if(R>m) ans=max(ans,query(L,R,add,rson));
return ans;
}
int main()
{
int t;
int n,m;
int a,b,op;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
build(1,n,1);
while(m--)
{
scanf("%d%d%d",&op,&a,&b);
if(op<3)
{
update(a+1,b+1,op,1,n,1);
}
else
{
printf("%d\n",query(a+1,b+1,op,1,n,1));
}
}
}
return 0;
}