【bzoj 1858】 [Scoi2010]序列操作 线段树

236 篇文章 0 订阅

第一次学习线段树的时候写的第一道题,想一想那时候天真的自己还是搞了一整天,用了将近标程2倍的代码量,记得那时候当屏幕出现ac是激动的样子,哎,人老了

#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 100010
#define lson u<<1,l,mid
#define rson u<<1|1,mid+1,r
using namespace std;
int n,m,k;
struct node{
	int l,r,s,l1,r1,l0,r0,add,one,zero,vis;//one表示最多有多少个连续的1 zero表示最多有多少个连续的0 
}nod[maxn*14];
void swap2(int *a, int *b){
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}
void pushdown(int u){
	int add=nod[u].add;
	int l=u<<1;
	int r=u<<1|1;
	if(add==1){
		nod[l].add=nod[r].add=1;
		nod[l].s=nod[r].s=0;
		nod[l].one=nod[l].l1=nod[l].r1=0;
		nod[r].one=nod[r].l1=nod[r].r1=0;
		nod[l].zero=nod[l].l0=nod[l].r0=nod[l].r-nod[l].l+1;
		nod[r].zero=nod[r].l0=nod[r].r0=nod[r].r-nod[r].l+1;
		
	}
	if(add==2){
		nod[l].add=nod[r].add=2;
		nod[l].s=nod[l].r-nod[l].l+1;
		nod[r].s=nod[r].r-nod[r].l+1;
		nod[l].zero=nod[l].l0=nod[l].r0=0;
		nod[r].zero=nod[r].l0=nod[r].r0=0;
		nod[l].one=nod[l].l1=nod[l].r1=nod[l].r-nod[l].l+1;
		nod[r].one=nod[r].l1=nod[r].r1=nod[r].r-nod[r].l+1;
		
	}
	if(add==3){
		bool ok1=1,ok2=1;
		if(nod[l].add==1||nod[l].add==2&&nod[l].vis!=-1){
			pushdown(l);
		}
		if(nod[r].add==1||nod[r].add==2&&nod[r].vis!=-1){
			pushdown(r);
		}
		if(nod[l].add==3){
			nod[l].add=0;ok1=0;
		}
		if(nod[r].add==3){
			nod[r].add=0;ok2=0;
		}
		if(ok1)nod[l].add=3;
		if(ok2)nod[r].add=3;
		nod[l].s=nod[l].r-nod[l].l+1-nod[l].s;
		nod[r].s=nod[r].r-nod[r].l+1-nod[r].s;
		swap2(&nod[l].l0,&nod[l].l1);
		swap2(&nod[l].r0,&nod[l].r1);
		swap2(&nod[l].one,&nod[l].zero);
		swap2(&nod[r].l0,&nod[r].l1);
		swap2(&nod[r].r0,&nod[r].r1);
		swap2(&nod[r].one,&nod[r].zero);
	}
	nod[u].add=0;
}
void pushup(int u){
        if(nod[u].add)pushdown(u);
		nod[u].s=nod[u<<1].s+nod[u<<1|1].s;
		nod[u].zero=max(max(nod[u<<1].zero,nod[u<<1|1].zero),nod[u<<1].r0+nod[u<<1|1].l0);
		nod[u].one=max(max(nod[u<<1].one,nod[u<<1|1].one),nod[u<<1].r1+nod[u<<1|1].l1);
		int llen=nod[u<<1].r-nod[u<<1].l +1;
		int rlen=nod[u<<1|1].r-nod[u<<1|1].l +1;
		int l=u<<1;
		int r=u<<1|1;
		if(nod[l].l1==llen){
			nod[u].l1=nod[l].l1 +nod[r].l1;
		}
	    if(nod[r].r1==rlen){
			nod[u].r1=nod[r].r1 +nod[l].r1;
		}
		if(nod[l].l1!=llen){
			nod[u].l1 =nod[l].l1;
		}
		if(nod[r].r1!=rlen){
			nod[u].r1 =nod[r].r1;
		}
		if(nod[l].l0==llen){
			nod[u].l0=nod[l].l0 +nod[r].l0;
		}
	    if(nod[r].r0==rlen){
			nod[u].r0=nod[r].r0 +nod[l].r0;
		}
		if(nod[l].l0!=llen){
			nod[u].l0 =nod[l].l0;
		}
		if(nod[r].r0!=rlen){
			nod[u].r0 =nod[r].r0;
		}
}
void build(int u,int l,int r){
	nod[u].l=l,nod[u].r=r;
	if(l==r){
		int x;
		scanf("%d",&x);
		nod[u].vis=-1;
		nod[u<<1|1].add=-1;
		nod[u].s=x;
		if(x==1){
			nod[u].one=1;
			nod[u].zero=0;
			nod[u].l1=1;
			nod[u].r1=1;
			nod[u].l0=0;
			nod[u].r0=0;
		}
		else{
			nod[u].one=0;
			nod[u].zero=1;
			nod[u].l1=0;
			nod[u].r1=0;
			nod[u].l0=1;
			nod[u].r0=1;
		}
		return;
	}
	int mid=(l+r)>>1;
	build(lson);
	build(rson);
	pushup(u);
}
void update(int u,int l,int r ,int x,int y,int add){
   if(nod[u].add)pushdown(u);
	if(l==x&&r==y){
		if(add==0){
			nod[u].add=1;
			nod[u].s=0;
			nod[u].one=nod[u].l1=nod[u].r1=0;
			nod[u].zero=nod[u].l0=nod[u].r0=nod[u].r-nod[u].l+1;
		}
		if(add==1){
			nod[u].add=2;
			nod[u].s=nod[u].r-nod[u].l+1;
			nod[u].one=nod[u].l1=nod[u].r1=nod[u].r-nod[u].l+1;
			nod[u].zero=nod[u].l0=nod[u].r0=0;
		}
		if(add==2){
			nod[u].add=3;
			nod[u].s=nod[u].r-nod[u].l+1-nod[u].s;
			swap2(&nod[u].l0,&nod[u].l1);
			swap2(&nod[u].r0,&nod[u].r1);
			swap2(&nod[u].one,&nod[u].zero);
		}
		return;
	}
	int mid=(l+r)>>1;
	if(x>mid)update(rson,x,y,add);
    else if(y<=mid)update(lson,x,y,add);
	else{
		update(lson,x,mid,add);
		update(rson,mid+1,y,add);
	}
	pushup(u);
}
int query1(int u,int l,int r,int x,int y){
	if(x==l&&y==r){
		return nod[u].s;
	}
	if(nod[u].add)pushdown(u);
	int mid=(l+r)>>1;
	if(x>mid)return query1(rson,x,y);
	else if(y<=mid)return query1(lson,x,y);
	else return query1(lson,x,mid)+query1(rson,mid+1,y);
}
int query(int u,int a,int b,int ok){
	if(ok){//左 
		if(nod[u].r-nod[u].r1<a){
			return b-a+1;
		}
		else return nod[u].r1;
	}
	else{
		if(nod[u].l1+a>b)return b-a+1;
		else return nod[u].l1;
	}
}

int query2(int u,int l,int r,int x,int y){
	if(x==l&&r==y){
		return nod[u].one;
	}
	if(nod[u].add)pushdown(u);
	int mid=(l+r)>>1;
	if(x>mid)return query2(rson,x,y);
	else if(y<=mid)return query2(lson,x,y);
	else {
		return max(max(query2(lson,x,mid),query2(rson,mid+1,y)),query(u<<1,x,mid,1)+query(u<<1|1,mid+1,y,0));
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	build(1,1,n);
	while(m--){
		int x,a,b;
		scanf("%d%d%d",&x,&a,&b);
		a++;
		b++;
		if(x==0)update(1,1,n,a,b,x);
		if(x==1)update(1,1,n,a,b,x);
		if(x==2)update(1,1,n,a,b,x);
		if(x==3){
			printf("%d\n",query1(1,1,n,a,b));
		}
		if(x==4)printf("%d\n",query2(1,1,n,a,b));
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值