做这道题之前就知道这题比较恶心,但是为了保持心态也没当作很难的题来做。
维护的标记比较多一些:
1、从左边开始的最多0的个数和1的个数
2、从右边开始的最多0的个数和1的个数
3、区间最大的0的个数和1的个数
4、区间0的个数和1的个数
5、是否反转
6、覆盖标记
有思路之后硬着头皮写,结果写下来一堆bug,改着比较烦,而且浪费时间。
比赛也没有那么多时间改bug,所以平时一定要养成注重细节的习惯,不然代码量一大就很容易出错。
需要注意的是先处理覆盖情况再处理翻转情况,因为覆盖时是一定把翻转标记清除了的,所以只有可能先覆盖再翻转。
下面是代码(比较冗长):
#include<cstdio>
#include<cstring>
#define lson l,m,rt << 1
#define rson m+1,r,rt << 1 | 1
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 100000 + 10;
struct tree
{
int maxL0,maxR0,Max0;
int maxL1,maxR1,Max1;
int cover,cnt0,cnt1;
bool reserve;
tree()
{
maxL0 = maxR0 = Max0 = 0;
maxL1 = maxR1 = Max1 = 0;
reserve = false;
cover = -1;
cnt0 = cnt1 = 0;
}
}Tree[maxn<<2],ans;
int n,m;
void init()
{
freopen("operation.in","r",stdin);
freopen("operation.out","w",stdout);
}
void swap(int &a,int &b)
{
int t;
t = a;a = b;b = t;
}
inline int max(int a,int b)
{
return a > b ? a : b;
}
void res(int rt)
{
swap(Tree[rt].maxL0,Tree[rt].maxL1);
swap(Tree[rt].maxR0,Tree[rt].maxR1);
swap(Tree[rt].Max0,Tree[rt].Max1);
swap(Tree[rt].cnt0,Tree[rt].cnt1);
}
void pushup(int rt,int l,int r)
{
int lc = rt << 1,rc = rt << 1 | 1;
int m = (l + r) >> 1;
Tree[rt].maxL0 = (Tree[lc].maxL0 == m - l + 1 ? Tree[lc].maxL0 + Tree[rc].maxL0 : Tree[lc].maxL0);
Tree[rt].maxL1 = (Tree[lc].maxL1 == m - l + 1 ? Tree[lc].maxL1 + Tree[rc].maxL1 : Tree[lc].maxL1);
Tree[rt].maxR0 = (Tree[rc].maxR0 == r - m ? Tree[lc].maxR0 + Tree[rc].maxR0 : Tree[rc].maxR0);
Tree[rt].maxR1 = (Tree[rc].maxR1 == r - m ? Tree[lc].maxR1 + Tree[rc].maxR1 : Tree[rc].maxR1);
Tree[rt].Max0 = max(Tree[lc].maxR0 + Tree[rc].maxL0,max(Tree[lc].Max0,Tree[rc].Max0));
Tree[rt].Max1 = max(Tree[lc].maxR1 + Tree[rc].maxL1,max(Tree[lc].Max1,Tree[rc].Max1));
Tree[rt].cnt0 = Tree[lc].cnt0 + Tree[rc].cnt0;
Tree[rt].cnt1 = Tree[lc].cnt1 + Tree[rc].cnt1;
}
void pushdown(int rt,int lc,int rc,int nu)
{
if(Tree[rt].cover != -1)
{
Tree[lc].cover = Tree[rc].cover = Tree[rt].cover;
Tree[lc].maxL0 = Tree[lc].maxR0 = Tree[lc].Max0 = Tree[rt].cover == 0 ? nu - (nu >> 1) : 0;
Tree[rc].maxL0 = Tree[rc].maxR0 = Tree[rc].Max0 = Tree[rt].cover == 0 ? (nu >> 1) : 0;
Tree[lc].maxL1 = Tree[lc].maxR1 = Tree[lc].Max1 = Tree[rt].cover == 0 ? 0 : nu - (nu >> 1);
Tree[rc].maxL1 = Tree[rc].maxR1 = Tree[rc].Max1 = Tree[rt].cover == 0 ? 0 : (nu >> 1);
Tree[lc].cnt0 = Tree[rt].cover == 0 ? nu - (nu >> 1) : 0;
Tree[rc].cnt0 = Tree[rt].cover == 0 ? (nu >> 1) : 0;
Tree[lc].cnt1 = Tree[rt].cover == 1 ? nu - (nu >> 1) : 0;
Tree[rc].cnt1 = Tree[rt].cover == 1 ? (nu >> 1) : 0;
Tree[lc].reserve = Tree[rc].reserve = false;
Tree[rt].cover = -1;
}
if(Tree[rt].reserve)
{
Tree[lc].reserve = !Tree[lc].reserve;
Tree[rc].reserve = !Tree[rc].reserve;
res(lc);res(rc);
Tree[rt].reserve = false;
}
}
void build(int l,int r,int rt)
{
if(l == r)
{
int tmp;
scanf("%d",&tmp);
if(tmp == 0)
{
Tree[rt].maxL0 = Tree[rt].maxR0 = Tree[rt].Max0 = 1;
Tree[rt].cnt0 = 1;
}
else
{
Tree[rt].maxL1 = Tree[rt].maxR1 = Tree[rt].Max1 = 1;
Tree[rt].cnt1 = 1;
}
return;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
pushup(rt,l,r);
}
void updata(int sc,int L,int R,int l,int r,int rt)
{
if(L <= l && r <= R)
{
if(sc == 2)Tree[rt].reserve = !Tree[rt].reserve,res(rt);
else
{
Tree[rt].reserve = false;
Tree[rt].cover = sc;
Tree[rt].maxL0 = Tree[rt].maxR0 = Tree[rt].Max0 = sc == 0 ? r - l + 1 : 0;
Tree[rt].maxL1 = Tree[rt].maxR1 = Tree[rt].Max1 = sc == 1 ? r - l + 1 : 0;
Tree[rt].cnt0 = sc == 0 ? r - l + 1 : 0;
Tree[rt].cnt1 = sc == 1 ? r - l + 1 : 0;
}
return;
}
pushdown(rt,rt<<1,rt<<1|1,r-l+1);
int m = (l + r) >> 1;
if(L <= m)updata(sc,L,R,lson);
if(R > m)updata(sc,L,R,rson);
pushup(rt,l,r);
}
void maintain(tree lc,tree rc,int l,int r)
{
int m = (l + r) >> 1;
ans.maxL0 = (lc.maxL0 == m - l + 1 ? lc.maxL0 + rc.maxL0 : lc.maxL0);
ans.maxL1 = (lc.maxL1 == m - l + 1 ? lc.maxL1 + rc.maxL1 : lc.maxL1);
ans.maxR0 = (rc.maxR0 == r - m ? lc.maxR0 + rc.maxR0 : rc.maxR0);
ans.maxR1 = (rc.maxR1 == r - m ? lc.maxR1 + rc.maxR1 : rc.maxR1);
ans.Max0 = max(lc.maxR0 + rc.maxL0,max(lc.Max0,rc.Max0));
ans.Max1 = max(lc.maxR1 + rc.maxL1,max(lc.Max1,rc.Max1));
ans.cnt0 = lc.cnt0 + rc.cnt0;
ans.cnt1 = lc.cnt1 + rc.cnt1;
}
tree query(int L,int R,int l,int r,int rt)
{
if(L <= l && r <= R)return Tree[rt];
pushdown(rt,rt<<1,rt<<1|1,r-l+1);
int m = (l + r) >> 1;
tree lc,rc;
if(L <= m)lc = query(L,R,lson);
if(R > m)rc = query(L,R,rson);
maintain(lc,rc,l,r);
return ans;
}
void readdata()
{
scanf("%d%d",&n,&m);
build(1,n,1);
for(int i = 1;i <= m;i++)
{
int p,l,r;
scanf("%d%d%d",&p,&l,&r);
l++;r++;
if(p <= 2)updata(p,l,r,1,n,1);
if(p == 3)printf("%d\n",query(l,r,1,n,1).cnt1);
if(p == 4)printf("%d\n",query(l,r,1,n,1).Max1);
}
}
int main()
{
init();
readdata();
return 0;
}