【bzoj4592】[Shoi2015]脑洞治疗仪

由于脑洞的序列不会改变,考虑用线段树维护区间内sum,左边0的个数,右边0的个数,区间内最大脑洞。对于查询l~r最大脑洞可以将l~r分成logn个区间,总复杂度O(nlogn)。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#define N 800005
using namespace std;
int n,m,p,x,y,l,r;
int sum[N],L[N],R[N],tg[N],v[N],Ans[N],rest,Hz,ans;
void down(int k)
{
	if (tg[k]!=-1)
	{
		int l=k<<1,r=l|1;
		tg[l]=tg[r]=tg[k];
		sum[l]=v[l]*tg[k];
		sum[r]=v[r]*tg[k];
		if (tg[k]==0) L[l]=R[l]=Ans[l]=v[l],L[r]=R[r]=Ans[r]=v[r];
		else L[l]=R[l]=L[r]=Ans[l]=R[r]=Ans[r]=0;
		tg[k]=-1;
	}
}
void up(int k)
{
	int l=k<<1,r=l|1;sum[k]=sum[l]+sum[r];
	if (!sum[l]) L[k]=L[l]+L[r];else L[k]=L[l];
	if (!sum[r]) R[k]=R[l]+R[r];else R[k]=R[r];
	Ans[k]=max(max(Ans[l],Ans[r]),R[l]+L[r]);
}
void build(int k,int l,int r)
{
	if (l==r){v[k]=1;return;}
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	v[k]=v[k<<1]+v[k<<1|1];
}
void add(int k,int l,int r,int x,int y)
{
	if (x<=l&&r<=y)
	{
		sum[k]=0;tg[k]=0;
		L[k]=R[k]=v[k];
		return;
	}
	int mid=(l+r)>>1;
	down(k);
	if (x<=mid) add(k<<1,l,mid,x,y);
	if (y>mid) add(k<<1|1,mid+1,r,x,y);
	up(k);
}
int Get(int k,int l,int r,int x,int y)
{
	if (x<=l&&r<=y) return sum[k];
	int mid=(l+r)>>1;
	down(k);
	int Ans=0;
	if (x<=mid) Ans+=Get(k<<1,l,mid,x,y);
	if (y>mid) Ans+=Get(k<<1|1,mid+1,r,x,y);
	return Ans;
}
void fix(int k,int l,int r,int x,int y)
{
	if (!rest) return;
	if (x<=l&&r<=y&&rest>=v[k]-sum[k])
	{
		rest-=v[k]-sum[k];
		tg[k]=1;Ans[k]=0;
		L[k]=R[k]=0;sum[k]=v[k];
		return;
	}
	down(k);
	int mid=(l+r)>>1;
	if (x<=mid) fix(k<<1,l,mid,x,y);
	if (y>mid) fix(k<<1|1,mid+1,r,x,y);
	up(k);
}
void qry(int k,int l,int r,int x,int y)
{
	if (x<=l&&r<=y)
	{
		ans=max(ans,Ans[k]);
		ans=max(ans,Hz+L[k]);
		if (R[k]==v[k]) Hz+=R[k];else Hz=R[k];
		return;
	}
	down(k);
	int mid=(l+r)>>1;
	if (x<=mid) qry(k<<1,l,mid,x,y);
	if (y>mid) qry(k<<1|1,mid+1,r,x,y);
}
int main()
{
	scanf("%d%d",&n,&m);
	build(1,1,n);
	sum[1]=v[1];tg[1]=1;
	for (int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&p,&l,&r);
		if (p==0) add(1,1,n,l,r);
		else if (p==1)
		{
			scanf("%d%d",&x,&y);
			rest=Get(1,1,n,l,r);
			add(1,1,n,l,r);
			fix(1,1,n,x,y);
		}
		else
		{
			ans=0;Hz=0;qry(1,1,n,l,r);
			printf("%d\n",ans);
		}
	}
	return 0;
}

  

posted @ 2016-05-23 14:48  Yangjiyuan  阅读(326)  评论(0编辑  收藏  举报