题目大意:
三个操作 两个查询
Change operations:
0 a b change all characters into '0's in [a , b] 区间全部变 0
1 a b change all characters into '1's in [a , b] 区间全部变 1
2 a b change all '0's into '1's and change all '1's into '0's in [a, b] 1变0 0变1
Output operations:
3 a b output the number of '1's in [a, b] 输出多少个1
4 a b output the length of the longest continuous '1' string in [a , b] 输出最长连续1
哭死了。。找了几个小时的BUG。。。结果是build 的 有一个变量名写错了 让一个变量没有赋值。。。
思路:
难点就在 2 操作上 对区间信息的维护上。 因为会1-0转换。所以要输出1 的信息的时候 还要记住0的信息
这样在转换的时候 就可以直接交换他们的信息就可以了。
然后用cov 标记 标记的方式 在代码上也注释出来了
然后输出需要输出最长连续的1 所以我们就要记录 最长1的 这一点我给个傻仔的链接。里面所说的POJ 3667 HOTEL 很像
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define lson num<<1,s,mid
#define rson num<<1|1,mid+1,e
#define maxn 100005
using namespace std;
int tre[maxn<<2];//区间最长1
int dan[maxn<<2];//区间最长0
int cnt[maxn<<2];//区间里1 的数量
int lemzer[maxn<<2];//区间左端点开始 最长连续的 0
int rimzer[maxn<<2];//----右----------------------0
int lemone[maxn<<2];//----左----------------------1
int rimone[maxn<<2];//----右----------------------1
int cov[maxn<<2];//-1未更新 0全是0 1有反转操作 2全是1
int n,m;
inline void Turn(int num,int len)//2操作的反转
{
swap(lemzer[num],lemone[num]);
swap(rimzer[num],rimone[num]);
swap(dan[num],tre[num]);
cnt[num]=len-cnt[num];
}
inline void pushup(int num,int s,int e)//这个和上面所说的hotel里的是一个概念
{
int mid=(s+e)>>1;
lemzer[num]=lemzer[num<<1];
lemone[num]=lemone[num<<1];
rimzer[num]=rimzer[num<<1|1];
rimone[num]=rimone[num<<1|1];
if(lemzer[num]==mid-s+1)lemzer[num]+=lemzer[num<<1|1];
if(rimzer[num]==e-mid)rimzer[num]+=rimzer[num<<1];
if(lemone[num]==mid-s+1)lemone[num]+=lemone[num<<1|1];
if(rimone[num]==e-mid)rimone[num]+=rimone[num<<1];
tre[num] = max(rimone[num<<1]+lemone[num<<1|1],max(tre[num<<1],tre[num<<1|1]));
dan[num] = max(rimzer[num<<1]+lemzer[num<<1|1],max(dan[num<<1],dan[num<<1|1]));
cnt[num] = cnt[num<<1]+cnt[num<<1|1];
}
void pushdown(int num,int s,int e)
{
if(cov[num]!=-1)
{
int mid=(s+e)>>1;
if(cov[num]==1)//这里要注意的就是 当这个区间存在反转操作的时候 下推的话 如果下个区间cov是0 就要变2 2 就要变0
{
if(cov[num<<1]!=0 && cov[num<<1]!=2)
cov[num<<1]=-cov[num<<1];
else
{
if(cov[num<<1]==0)cov[num<<1]=2;
else if(cov[num<<1]==2)cov[num<<1]=0;
}
Turn(num<<1,mid-s+1);
if(cov[num<<1|1]!=0 && cov[num<<1|1]!=2)
cov[num<<1|1]=-cov[num<<1|1];
else
{
if(cov[num<<1|1]==0)cov[num<<1|1]=2;
else if(cov[num<<1|1]==2)cov[num<<1|1]=0;
}
Turn(num<<1|1,e-mid);
}
else
{
cov[num<<1]=cov[num<<1|1]=cov[num];
cnt[num<<1]=tre[num<<1]=lemone[num<<1]=rimone[num<<1]=cov[num]==2?mid-s+1:0;
dan[num<<1]=lemzer[num<<1]=rimzer[num<<1]=cov[num]==2?0:mid-s+1;
cnt[num<<1|1]=tre[num<<1|1]=lemone[num<<1|1]=rimone[num<<1|1]=cov[num]==2?e-mid:0;
dan[num<<1|1]=lemzer[num<<1|1]=rimzer[num<<1|1]=cov[num]==2?0:e-mid;
}
cov[num]=-1;
}
}
void build(int num,int s,int e)
{
cov[num]=-1;
if(s==e)
{
int a;
scanf("%d",&a);
if(a==1)
{
cnt[num]=tre[num]=lemone[num]=rimone[num]=1;
dan[num]=lemzer[num]=rimzer[num]=0;//就是。。。错在。。这里。。。写成了两个 lemzer。。。头疼的变量名
cov[num]=2;
}
else
{
cnt[num]=tre[num]=lemone[num]=rimone[num]=0;
dan[num]=lemzer[num]=rimzer[num]=1;
cov[num]=0;
}
return;
}
int mid=(s+e)>>1;
build(lson);
build(rson);
pushup(num,s,e);
}
void update(int num,int s,int e,int l,int r,int op)
{
if(l<=s && r>=e)
{
if(op==0)
{
lemzer[num]=rimzer[num]=dan[num]=e-s+1;
lemone[num]=rimone[num]=tre[num]=0;
cnt[num]=0;
cov[num]=0;
}
else if(op==1)
{
lemzer[num]=rimzer[num]=dan[num]=0;
lemone[num]=rimone[num]=tre[num]=e-s+1;
cnt[num]=e-s+1;
cov[num]=2;
}
else
{
if(cov[num]==2)cov[num]=0;//这里也要注意。。
else if(cov[num]==0)cov[num]=2;
else cov[num]=-cov[num];
Turn(num,e-s+1);
}
return;
}
int mid=(s+e)>>1;
pushdown(num,s,e);
if(l<=mid)update(lson,l,r,op);
if(r>mid)update(rson,l,r,op);
pushup(num,s,e);
}
int query(int num,int s,int e,int l,int r,int op)
{
if(l<=s && r>=e)
{
if(op==3)return cnt[num];
else return tre[num];
}
int mid=(s+e)>>1;
pushdown(num,s,e);
if(op==3)
{
if(r<=mid)return query(lson,l,r,op);
else if(l>mid)return query(rson,l,r,op);
else return query(lson,l,mid,op)+query(rson,mid+1,r,op);
}
else
{
if(r<=mid)return query(lson,l,r,op);
else if(l>mid)return query(rson,l,r,op);
else
{
int tmp=min(mid-l+1,rimone[num<<1])+min(r-mid,lemone[num<<1|1]);//这里是我没想到的。。大家自己斟酌一下。。
return max(tmp,max(query(lson,l,mid,op),query(rson,mid+1,r,op)));
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
build(1,1,n);
while(m--)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
b++;
c++;
if(a<=2)
update(1,1,n,b,c,a);
else
printf("%d\n",query(1,1,n,b,c,a));
}
}
return 0;
}
/*
1
10 1000
1 1 1 1 1 0 1 1 1 1
2 2 3
2 3 5
2 5 8
*/