【BZOJ】【P1858】【Scoi2010】【序列操作】【题解】【线段树】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1858

锻炼代码能力的线段树裸题

Code:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cctype>
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define L i<<1
#define R i<<1|1
using namespace std;
const int maxn=1e5+5;
int a[maxn];
int n,m;
int getint(){
	int res=0;char c=getchar();
	while(!isdigit(c))c=getchar();
	while(isdigit(c))res=res*10+c-'0',c=getchar();
	return res;
}
struct tup{
	int x,y,z;
	tup(int _x=0,int _y=0,int _z=0):x(_x),y(_y),z(_z){}
};
int max5(int a,int b,int c,int d,int e){return max(e,max(max(a,b),max(c,d)));}
struct seg_tree{
	struct node{
		int lazy,rev,sum0,sum1,ls1,ss1,rs1,ls0,rs0,ss0;
		node(){
			lazy=-1,rev=0,sum0=0,sum1=0,ls1=0,ss1=0,rs1=0,ls0=0,rs0=0,ss0=0;
		}
	}t[maxn<<2];
	void build(int i,int l,int r){
		if(l==r){
			t[i].sum0=t[i].ls0=t[i].ss0=t[i].rs0=a[l]==0;
			t[i].sum1=t[i].ls1=t[i].ss1=t[i].rs1=a[l]==1;	
			return;		
		}int mid=(l+r)>>1;
		build(lson);build(rson);
		rz(i,l,r);
	}
	void rz(int i,int l,int r){
		int mid=(l+r)>>1;
		tup l0,r0,ans;
		t[i].sum0=t[L].sum0+t[R].sum0;
		t[i].sum1=t[L].sum1+t[R].sum1;
		
		t[i].ls0=t[L].ls0;
		t[i].rs0=t[R].rs0;
		t[i].ls1=t[L].ls1;
		t[i].rs1=t[R].rs1;		
		if(t[L].ls0==(mid-l+1))t[i].ls0=t[L].ls0+t[R].ls0;
		if(t[L].ls1==(mid-l+1))t[i].ls1=t[L].ls1+t[R].ls1;
		if(t[R].rs0==(r-mid))t[i].rs0=t[R].rs0+t[L].rs0;
		if(t[R].rs1==(r-mid))t[i].rs1=t[R].rs1+t[L].rs1;
		t[i].ss0=max5(t[L].ss0,t[R].ss0,t[i].ls0,t[i].rs0,t[L].rs0+t[R].ls0);
		t[i].ss1=max5(t[L].ss1,t[R].ss1,t[i].ls1,t[i].rs1,t[L].rs1+t[R].ls1);
	}
	void pushdown(int i,int l,int r){
		int mid=(l+r)>>1;
				
		if(t[i].rev){
			swap(t[L].sum0,t[L].sum1);swap(t[L].ls1,t[L].ls0);
			swap(t[L].ss1,t[L].ss0);swap(t[L].rs1,t[L].rs0);
			swap(t[R].sum0,t[R].sum1);swap(t[R].ls1,t[R].ls0);
			swap(t[R].ss1,t[R].ss0);swap(t[R].rs1,t[R].rs0);
			t[L].rev^=1;t[R].rev^=1;
			if(~t[L].lazy)t[L].lazy^=1;
			if(~t[R].lazy)t[R].lazy^=1;	
			t[i].rev=0;
		}
		if(t[i].lazy!=-1){
			t[L].lazy=t[i].lazy;
			t[L].sum0=(mid-l+1)*(t[i].lazy==0);
			t[L].sum1=(mid-l+1)*(t[i].lazy==1);
			t[L].ls0=t[L].ss0=t[L].rs0=(mid-l+1)*(t[i].lazy==0);
			t[L].ls1=t[L].ss1=t[L].rs1=(mid-l+1)*(t[i].lazy==1);
			
			t[R].lazy=t[i].lazy;
			t[R].sum0=(r-mid)*(t[i].lazy==0);
			t[R].sum1=(r-mid)*(t[i].lazy==1);
			t[R].ls0=t[R].ss0=t[R].rs0=(r-mid)*(t[i].lazy==0);
			t[R].ls1=t[R].ss1=t[R].rs1=(r-mid)*(t[i].lazy==1);
			
			t[i].lazy=-1;
		}		
	}
	void Change(int i,int l,int r,int l0,int r0,int col){
		if(l0<=l&&r0>=r){
			t[i].lazy=col;
			t[i].sum0=(r-l+1)*(t[i].lazy==0);
			t[i].sum1=(r-l+1)*(t[i].lazy==1);
			t[i].ls0=t[i].ss0=t[i].rs0=(r-l+1)*(t[i].lazy==0);
			t[i].ls1=t[i].ss1=t[i].rs1=(r-l+1)*(t[i].lazy==1);
			return;
		}pushdown(i,l,r);
		int mid=(l+r)>>1;
		if(l0<=mid)Change(lson,l0,r0,col);
		if(r0>mid)Change(rson,l0,r0,col);
		rz(i,l,r);
	}
	void Rev(int i,int l,int r,int l0,int r0){
		if(l0<=l&&r0>=r){
			t[i].rev^=1;
			if(~t[i].lazy)t[i].lazy^=1;
			swap(t[i].sum0,t[i].sum1);swap(t[i].ls1,t[i].ls0);
			swap(t[i].ss1,t[i].ss0);swap(t[i].rs1,t[i].rs0);
			return;
		}pushdown(i,l,r);
		int mid=(l+r)>>1;
		if(l0<=mid)Rev(lson,l0,r0);
		if(r0>mid)Rev(rson,l0,r0);
		rz(i,l,r);		
	}
	int One(int i,int l,int r,int l0,int r0){
		if(l0<=l&&r0>=r)
			return t[i].sum1;
		pushdown(i,l,r);
		int mid=(l+r)>>1,ans=0;
		if(l0<=mid)ans+=One(lson,l0,r0);
		if(r0>mid)ans+=One(rson,l0,r0);
		return ans;
	}
	tup Sone(int i,int l,int r,int l0,int r0){
		if(l0<=l&&r0>=r)
			return tup(t[i].ls1,t[i].ss1,t[i].rs1);	
		pushdown(i,l,r);
		int mid=(l+r)>>1;tup ans,lef,rig;
		if(l0<=mid)lef=Sone(lson,l0,r0);		
		if(r0>mid)rig=Sone(rson,l0,r0);
		if(l0>mid)return rig;
		if(r0<=mid)return lef;
		ans.x=lef.x;ans.z=rig.z;
		if(lef.x==mid-l+1)ans.x=lef.x+rig.x;
		if(rig.z==r-mid)ans.z=rig.z+lef.z;
		ans.y=max5(lef.y,rig.y,ans.x,ans.y,lef.z+rig.x);
		return ans;			
	}
}T;
int main(){
	n=getint(),m=getint();
	for(int i=1;i<=n;i++)a[i]=getint();
	T.build(1,1,n);
	while(m--){
		int op=getint(),l=getint()+1,r=getint()+1;
		if(op==0){T.Change(1,1,n,l,r,0);}
		if(op==1){T.Change(1,1,n,l,r,1);}
		if(op==2){T.Rev(1,1,n,l,r);}
		if(op==3){printf("%d\n",T.One(1,1,n,l,r));}
		if(op==4){printf("%d\n",T.Sone(1,1,n,l,r).y);}
	}return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值