[BZOJ4592][SHOI2015]脑洞治疗仪
bzoj
luogu
题意:给你一段01序列,要求支持如下操作:(下面把正常脑区域视为0,脑洞视为1)
1、把一段区间全部改成1.
2、把一段区间全部的0挖出来(然后这个区间也就全部变成了1),把这些0放到另一个区间上的1位置,原本的0位置不需要再放,如果0不够就优先放前面。
3、求最大连续1的和。
sol
线段树基本操作。
维护每个区间的和、最大连续段长度、左边最大连续段长度、右边最大连续段长度、是否全是1.
都是基本操作。一遍A
code
#include<cstdio>
#include<algorithm>
using namespace std;
int gi()
{
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 2e5+5;
struct Data{int sum,mx,ml,mr,ful;}t[N<<2];
Data operator + (Data a,Data b)
{
Data c;
c.sum=a.sum+b.sum;
c.mx=max(max(a.mx,b.mx),a.mr+b.ml);
c.ml=a.ful?a.sum+b.ml:a.ml;
c.mr=b.ful?b.sum+a.mr:b.mr;
c.ful=a.ful&b.ful;
return c;
}
int n,m,tag[N<<2],Sum;
void build(int x,int l,int r)
{
tag[x]=-1;
if (l==r) return;
int mid=l+r>>1;
build(x<<1,l,mid);build(x<<1|1,mid+1,r);
t[x]=t[x<<1]+t[x<<1|1];
}
void cover(int x,int l,int r,int c)
{
if (c)
{
t[x].sum=t[x].mx=t[x].ml=t[x].mr=r-l+1;t[x].ful=1;
tag[x]=1;
}
else
{
t[x].sum=t[x].mx=t[x].ml=t[x].mr=t[x].ful=0;
tag[x]=0;
}
}
void pushdown(int x,int l,int r)
{
if (tag[x]!=-1)
{
int mid=l+r>>1;
cover(x<<1,l,mid,tag[x]);cover(x<<1|1,mid+1,r,tag[x]);
tag[x]=-1;
}
}
void add(int x,int l,int r,int ql,int qr)
{
if (l>=ql&&r<=qr) {cover(x,l,r,1);return;}
pushdown(x,l,r);int mid=l+r>>1;
if (ql<=mid) add(x<<1,l,mid,ql,qr);
if (qr>mid) add(x<<1|1,mid+1,r,ql,qr);
t[x]=t[x<<1]+t[x<<1|1];
}
void del(int x,int l,int r,int ql,int qr)
{
if (!Sum) return;
if (l>=ql&&r<=qr&&Sum>=t[x].sum)
{
Sum-=t[x].sum;cover(x,l,r,0);
return;
}
pushdown(x,l,r);int mid=l+r>>1;
if (ql<=mid) del(x<<1,l,mid,ql,qr);
if (qr>mid) del(x<<1|1,mid+1,r,ql,qr);
t[x]=t[x<<1]+t[x<<1|1];
}
Data query(int x,int l,int r,int ql,int qr)
{
if (l>=ql&&r<=qr) return t[x];
pushdown(x,l,r);int mid=l+r>>1;
if (qr<=mid) return query(x<<1,l,mid,ql,qr);
if (ql>mid) return query(x<<1|1,mid+1,r,ql,qr);
return query(x<<1,l,mid,ql,qr)+query(x<<1|1,mid+1,r,ql,qr);
}
int main()
{
n=gi();m=gi();build(1,1,n);
while (m--)
{
int opt=gi();
if (!opt)
{
int l=gi(),r=gi();
add(1,1,n,l,r);
}
if (opt==1)
{
int l=gi(),r=gi();
Sum=r-l+1-query(1,1,n,l,r).sum;
add(1,1,n,l,r);
l=gi(),r=gi();
del(1,1,n,l,r);
}
if (opt==2)
{
int l=gi(),r=gi();
printf("%d\n",query(1,1,n,l,r).mx);
}
}
return 0;
}