[SCOI2010]序列操作

操作0、1:区间赋值

操作2:区间异或

操作3:区间求和

操作4:区间最长连续段

我们用线段树打lazy标记的方式维护:某段区间从左向右和从右向左延伸的0和1的长度、某段区间内0和1的最长长度、区间和。

然后分类讨论pushdown与pushup即可

#include"cstdio"
#include"cstring"
#include"iostream"
#include"algorithm"
using namespace std;

const int MAXN=1<<17;

int n,m;
int a[MAXN];
int lef[2][MAXN<<1],rig[2][MAXN<<1],mx[2][MAXN<<1];
int sm[MAXN<<1],tag[MAXN<<1],chg[MAXN<<1];

inline int read()
{
	int x=0;char ch=getchar();
	while(ch<'0'||'9'<ch) ch=getchar();
	while('0'<=ch&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x;
}

inline void pushup(int k,int l,int r)
{
	if(l==r) return;
	int i=k<<1,mid=l+r>>1;
	lef[0][k]=lef[0][i]==mid-l+1?lef[0][i]+lef[0][i|1]:lef[0][i];
	lef[1][k]=lef[1][i]==mid-l+1?lef[1][i]+lef[1][i|1]:lef[1][i];
	rig[0][k]=rig[0][i|1]==r-mid?rig[0][i|1]+rig[0][i]:rig[0][i|1];
	rig[1][k]=rig[1][i|1]==r-mid?rig[1][i|1]+rig[1][i]:rig[1][i|1];
	mx[0][k]=max(rig[0][i]+lef[0][i|1],max(mx[0][i],mx[0][i|1]));
	mx[1][k]=max(rig[1][i]+lef[1][i|1],max(mx[1][i],mx[1][i|1]));
	sm[k]=sm[i]+sm[i|1];
	return;
}

void build(int k,int l,int r)
{
	chg[k]=-1;
	if(l==r){
		if(a[l]) sm[k]=1;
		lef[a[l]][k]=rig[a[l]][k]=mx[a[l]][k]=1;
		return;
	}int i=k<<1,mid=l+r>>1;
	build(i,l,mid);build(i|1,mid+1,r);
	pushup(k,l,r);
	return;
}

void pushdown(int k,int l,int r)
{
	if(l==r||(!tag[k]&&chg[k]==-1)) return;
	int i=k<<1,mid=l+r>>1;
	if(tag[k]){
		if(chg[i]!=-1) chg[i]^=1;
		if(chg[i|1]!=-1) chg[i|1]^=1;
		tag[i]^=1;tag[i|1]^=1;
		sm[i]=mid-l+1-sm[i];sm[i|1]=r-mid-sm[i|1];
		swap(lef[0][i],lef[1][i]),swap(rig[0][i],rig[1][i]),swap(mx[0][i],mx[1][i]);
		swap(lef[0][i|1],lef[1][i|1]),swap(rig[0][i|1],rig[1][i|1]),swap(mx[0][i|1],mx[1][i|1]);
		tag[k]=0;
	}if(chg[k]!=-1){
		tag[i]=tag[i|1]=0;chg[i]=chg[i|1]=chg[k];
		sm[i]=chg[k]?mid-l+1:0;sm[i|1]=chg[k]?r-mid:0;
		lef[chg[k]][i]=rig[chg[k]][i]=mx[chg[k]][i]=mid-l+1;
		lef[chg[k]^1][i]=rig[chg[k]^1][i]=mx[chg[k]^1][i]=0;
		lef[chg[k]][i|1]=rig[chg[k]][i|1]=mx[chg[k]][i|1]=r-mid;
		lef[chg[k]^1][i|1]=rig[chg[k]^1][i|1]=mx[chg[k]^1][i|1]=0;
		chg[k]=-1;
	}return;
}

void cchg(int k,int l,int r,int le,int ri,int v)
{
	pushdown(k,l,r);
	if(le<=l&&r<=ri){
		sm[k]=v?r-l+1:0;
		lef[v][k]=rig[v][k]=mx[v][k]=r-l+1;
		lef[v^1][k]=rig[v^1][k]=mx[v^1][k]=0;
		chg[k]=v;
		return;
	}int i=k<<1,mid=l+r>>1;
	if(le<=mid) cchg(i,l,mid,le,ri,v);
	if(mid<ri) cchg(i|1,mid+1,r,le,ri,v);
	pushup(k,l,r);
	return;
}

void ctag(int k,int l,int r,int le,int ri)
{
	pushdown(k,l,r);
	if(le<=l&&r<=ri){
		tag[k]=1;
		sm[k]=r-l+1-sm[k];
		swap(lef[0][k],lef[1][k]);
		swap(rig[0][k],rig[1][k]);
		swap(mx[0][k],mx[1][k]);
		return;
	}int i=k<<1,mid=l+r>>1;
	if(le<=mid) ctag(i,l,mid,le,ri);
	if(mid<ri) ctag(i|1,mid+1,r,le,ri);
	pushup(k,l,r);
	return;
}

int cask1(int k,int l,int r,int le,int ri)
{
	pushdown(k,l,r);pushup(k,l,r);
	if(le<=l&&r<=ri) return sm[k];
	int i=k<<1,mid=l+r>>1,sum=0;
	if(le<=mid) sum+=cask1(i,l,mid,le,ri);
	if(mid<ri) sum+=cask1(i|1,mid+1,r,le,ri);
	return sum;
}

int cask2(int k,int l,int r,int le,int ri)
{
	pushdown(k,l,r);pushup(k,l,r);
	if(le<=l&&r<=ri) return mx[1][k];
	int i=k<<1,mid=l+r>>1,mxx=0;
	if(le<=mid&&mid<ri) mxx=max(max(cask2(i,l,mid,le,ri),cask2(i|1,mid+1,r,le,ri)),min(mid-le+1,rig[1][i])+min(ri-mid,lef[1][i|1]));
	else if(le<=mid) mxx=cask2(i,l,mid,le,ri);
	else if(mid<ri) mxx=cask2(i|1,mid+1,r,le,ri);
	return mxx;
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i) a[i]=read();
	build(1,1,n);
	while(m--){
		int p=read(),l=read()+1,r=read()+1;
		if(p==0) cchg(1,1,n,l,r,0);
		else if(p==1) cchg(1,1,n,l,r,1);
		else if(p==2) ctag(1,1,n,l,r);
		else if(p==3) printf("%d\n",cask1(1,1,n,l,r));
		else printf("%d\n",cask2(1,1,n,l,r));
	}return 0;
}
posted @ 2019-01-01 21:22  A·H  阅读(113)  评论(0编辑  收藏  举报