五种操作,三种更新,两种查询,合并区间。。。算是比较经典的题目了,操作和查询都比较常规,合并的题目之前也写过几道。。。不过这道题目要用到两种lazy标记,因为异或和全为1,全为0不能合并成一种。。所以写pushdown和写updata的时候要小心,先全改,再异或,先异或,再全改,先异或再异或。。。几种情况都要考虑清楚,不然容易错。。。总的来说这道题目还是比较经典的。。。
#include <iostream>
#include <sstream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <climits>
#define maxn 400005
#define eps 1e-6
#define mod 1000000007
#define INF 99999999
#define lowbit(x) (x&(-x))
#define lson o<<1, L, mid
#define rson o<<1 | 1, mid+1, R
typedef long long LL;
using namespace std;
int mark1[maxn], mark2[maxn];
int sum[maxn], init[maxn];
int lmax[2][maxn], rmax[2][maxn];
int segmax[2][maxn], segnum[2][maxn];
int ansl[maxn], ansv[maxn];
int n, m, k;
int ql, qr, ans;
void pushup(int o, int L, int R, int c)
{
int tmp=0, mid=(L+R)>>1;
if(rmax[c][o<<1] && lmax[c][o<<1 | 1]) tmp=rmax[c][o<<1]+lmax[c][o<<1 | 1];
if(tmp>=segmax[c][o<<1] && tmp>=segmax[c][o<<1 | 1])
segmax[c][o]=tmp, segnum[c][o]=mid-rmax[c][o<<1]+1;
else if(segmax[c][o<<1]>segmax[c][o<<1 | 1])
segmax[c][o]=segmax[c][o<<1], segnum[c][o]=segnum[c][o<<1];
else segmax[c][o]=segmax[c][o<<1 | 1], segnum[c][o]=segnum[c][o<<1 | 1];
if(segnum[c][o]==L) lmax[c][o]=segmax[c][o];
else lmax[c][o]=lmax[c][o<<1];
if(segnum[c][o]+segmax[c][o]-1==R) rmax[c][o]=segmax[c][o];
else rmax[c][o]=rmax[c][o<<1 | 1];
sum[o]=sum[o<<1]+sum[o<<1 | 1];
}
void build(int o, int L, int R)
{
if(L==R){
sum[o]=init[L];
if(init[L]){
segmax[0][o]=0, segmax[1][o]=1, segnum[0][o]=L, segnum[1][o]=L;
lmax[0][o]=0, rmax[0][o]=0, lmax[1][o]=1, rmax[1][o]=1;
}
else{
segmax[0][o]=1, segmax[1][o]=0, segnum[0][o]=L, segnum[1][o]=L;
lmax[0][o]=1, rmax[0][o]=1, lmax[1][o]=0, rmax[1][o]=0;
}
return;
}
int mid=(R+L)>>1;
build(lson);
build(rson);
pushup(o, L, R, 0);
pushup(o, L, R, 1);
}
void pushdown1(int o, int L, int R)
{
if(mark1[o]==-1) return;
int mid=(R+L)>>1;
if(mark1[o]==0){
segnum[0][o<<1]=L, segnum[0][o<<1 | 1]=mid+1;
lmax[0][o<<1]=rmax[0][o<<1]=segmax[0][o<<1]=mid-L+1;
lmax[0][o<<1 | 1]=rmax[0][o<<1 | 1]=segmax[0][o<<1 | 1]=R-mid;
segnum[1][o<<1]=L, segnum[1][o<<1 | 1]=mid+1;
lmax[1][o<<1]=rmax[1][o<<1]=segmax[1][o<<1]=0;
lmax[1][o<<1 | 1]=rmax[1][o<<1 | 1]=segmax[1][o<<1 | 1]=0;
sum[o<<1]=sum[o<<1 | 1]=0;
}
else{
segnum[1][o<<1]=L, segnum[1][o<<1 | 1]=mid+1;
lmax[1][o<<1]=rmax[1][o<<1]=segmax[1][o<<1]=mid-L+1;
lmax[1][o<<1 | 1]=rmax[1][o<<1 | 1]=segmax[1][o<<1 | 1]=R-mid;
segnum[0][o<<1]=L, segnum[0][o<<1 | 1]=mid+1;
lmax[0][o<<1]=rmax[0][o<<1]=segmax[0][o<<1]=0;
lmax[0][o<<1 | 1]=rmax[0][o<<1 | 1]=segmax[0][o<<1 | 1]=0;
sum[o<<1]=mid-L+1, sum[o<<1 | 1]=R-mid;
}
mark1[o<<1]=mark1[o<<1 | 1]=mark1[o];
mark1[o]=-1, mark2[o]=0;
}
void pushdown2(int o, int L, int R)
{
if(!mark2[o]) return;
int mid=(R+L)>>1;
swap(lmax[0][o<<1], lmax[1][o<<1]), swap(lmax[0][o<<1 | 1], lmax[1][o<<1 | 1]);
swap(rmax[0][o<<1], rmax[1][o<<1]), swap(rmax[0][o<<1 | 1], rmax[1][o<<1 | 1]);
swap(segmax[0][o<<1], segmax[1][o<<1]), swap(segmax[0][o<<1 | 1], segmax[1][o<<1 | 1]);
swap(segnum[0][o<<1], segnum[1][o<<1]), swap(segnum[0][o<<1 | 1], segnum[1][o<<1 | 1]);
sum[o<<1]=mid-L+1-sum[o<<1], sum[o<<1 | 1]=R-mid-sum[o<<1 | 1];
if(mark1[o<<1]!=-1) mark1[o<<1]^=1, mark2[o<<1]=0;
else mark2[o<<1]^=1;
if(mark1[o<<1 | 1]!=-1) mark1[o<<1 | 1]^=1, mark2[o<<1 | 1]=0;
else mark2[o<<1 | 1]^=1;
mark2[o]=0;
}
void updata(int o, int L, int R)
{
if(ql<=L && qr>=R){
if(k==1){
mark1[o]=0, mark2[o]=0;
segnum[0][o]=segnum[1][o]=L, sum[o]=0;
lmax[0][o]=rmax[0][o]=segmax[0][o]=R-L+1;
lmax[1][o]=rmax[1][o]=segmax[1][o]=0;
}
if(k==2){
mark1[o]=1, mark2[o]=0;
segnum[0][o]=segnum[1][o]=L, sum[o]=R-L+1;
lmax[0][o]=rmax[0][o]=segmax[0][o]=0;
lmax[1][o]=rmax[1][o]=segmax[1][o]=R-L+1;
}
if(k==3){
if(mark1[o]!=-1) mark1[o]^=1;
else mark2[o]^=1;
sum[o]=R-L+1-sum[o];
swap(segmax[0][o], segmax[1][o]);
swap(segnum[0][o], segnum[1][o]);
swap(lmax[0][o], lmax[1][o]);
swap(rmax[0][o], rmax[1][o]);
}
return;
}
pushdown2(o, L, R);
pushdown1(o, L, R);
int mid=(R+L)>>1;
if(ql<=mid) updata(lson);
if(qr>mid) updata(rson);
pushup(o, L, R, 0);
pushup(o, L, R, 1);
}
void _query(int o, int L, int R)
{
if(ql<=L && qr>=R){
ans+=sum[o];
return;
}
pushdown2(o, L, R);
pushdown1(o, L, R);
int mid=(R+L)>>1;
if(ql<=mid) _query(lson);
if(qr>mid) _query(rson);
pushup(o, L, R, 0);
pushup(o, L, R, 1);
}
void _pushup(int o, int L, int R)
{
int mid=(R+L)>>1, tmp=0;
if(ql>mid || qr<=mid || !lmax[1][o<<1 | 1] || !rmax[1][o<<1]) tmp=0;
else tmp=min(mid+lmax[1][o<<1 | 1], qr)-max(mid-rmax[1][o<<1]+1, ql)+1;
if(tmp>=ansv[o<<1] && tmp>=ansv[o<<1 | 1]) ansv[o]=tmp, ansl[o]=max(mid-rmax[1][o<<1]+1, ql);
else if(ansv[o<<1]>ansv[o<<1 | 1]) ansv[o]=ansv[o<<1], ansl[o]=ansl[o<<1];
else ansv[o]=ansv[o<<1 | 1], ansl[o]=ansl[o<<1 | 1];
ansl[o<<1]=ansl[o<<1 | 1]=ansv[o<<1]=ansv[o<<1 | 1]=0;
}
void query(int o, int L, int R)
{
if(ql<=L && qr>=R){
ansl[o]=segnum[1][o], ansv[o]=segmax[1][o];
return;
}
pushdown2(o, L, R);
pushdown1(o, L, R);
int mid=(R+L)>>1;
if(ql<=mid) query(lson);
if(qr>mid) query(rson);
pushup(o, L, R, 0);
pushup(o, L, R, 1);
_pushup(o, L, R);
}
void solve(void)
{
while(m--){
scanf("%d%d%d",&k,&ql,&qr);
k++, ql++, qr++;
if(k>=4){
ans=0;
if(k==4){
_query(1, 1, n);
printf("%d\n", ans);
}
else{
query(1, 1, n);
printf("%d\n", ansv[1]);
}
}
else updata(1, 1, n);
}
}
int main(void)
{
int _;
while(scanf("%d",&_)!=EOF){
while(_--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&init[i]);
memset(mark1, -1, sizeof mark1);
memset(mark2, 0, sizeof mark2);
memset(ansl, 0, sizeof ansl);
memset(ansv, 0, sizeof ansv);
build(1, 1, n);
solve();
}
}
return 0;
}