[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;
}
posted @ 2018-03-25 22:25  租酥雨  阅读(243)  评论(0编辑  收藏  举报