• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

【洛谷】 P2572 [SCOI2010]序列操作 (线段树)

开发技术 开发技术 6小时前 1次浏览

P2572 [SCOI2010]序列操作

【洛谷】 P2572 [SCOI2010]序列操作   (线段树)

对于区间覆盖,我们都习以为常了,对于连续的(1)这种线段树区间连续问题,维护左儿子右端点连续最大和右儿子左端点连续最大即可解决,那么取反操作就是将区间连续的(1)和连续的(0)的数量交换,分别对(0)(1)维护连续也可解决,再看懒标记的问题,首先赋值会覆盖取反标记,然后取反标记的时候,如果当前区间有赋值标记,那么赋值标记也应该取反!!!!(这里卡了我好久,调了半天),最后就是查询连续最大值,可以当成一个板子吧,分三种情况return。

#include <bits/stdc++.h>

using namespace std;
const int N=1e6+10;
const int mod=1e9+7;
#define ll long long
#define pb push_back

int n,m;
int a[N];

struct Node{
	int l,r;
	int tag;
	int rev;
	int sum;
	int mx0;
	int lmx0,rmx0;
	int mx1;
	int lmx1,rmx1;
}tr[N<<4];

void push_up(int u){
	tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;

	if(tr[u<<1].mx1==tr[u<<1].r-tr[u<<1].l+1) tr[u].lmx1=tr[u<<1].mx1+tr[u<<1|1].lmx1;
	else tr[u].lmx1=tr[u<<1].lmx1;

	if(tr[u<<1|1].mx1==tr[u<<1|1].r-tr[u<<1|1].l+1) tr[u].rmx1=tr[u<<1|1].mx1+tr[u<<1].rmx1;
	else tr[u].rmx1=tr[u<<1|1].rmx1;

	if(tr[u<<1].mx0==tr[u<<1].r-tr[u<<1].l+1) tr[u].lmx0=tr[u<<1].mx0+tr[u<<1|1].lmx0;
	else tr[u].lmx0=tr[u<<1].lmx0;

	if(tr[u<<1|1].mx0==tr[u<<1|1].r-tr[u<<1|1].l+1) tr[u].rmx0=tr[u<<1|1].mx0+tr[u<<1].rmx0;
	else tr[u].rmx0=tr[u<<1|1].rmx0;

	tr[u].mx1=max({tr[u<<1].mx1,tr[u<<1|1].mx1,tr[u<<1].rmx1+tr[u<<1|1].lmx1});
	tr[u].mx0=max({tr[u<<1].mx0,tr[u<<1|1].mx0,tr[u<<1].rmx0+tr[u<<1|1].lmx0});
}

void push_down(int u){
	if(tr[u].tag!=-1){
		tr[u].rev=0;
		tr[u<<1].rev=tr[u<<1|1].rev=0;
		if(tr[u].tag==0){
			tr[u<<1].sum=tr[u<<1].mx1=tr[u<<1].lmx1=tr[u<<1].rmx1=0;
			tr[u<<1].mx0=tr[u<<1].lmx0=tr[u<<1].rmx0=tr[u<<1].r-tr[u<<1].l+1;
			tr[u<<1].tag=0;

			tr[u<<1|1].sum=tr[u<<1|1].mx1=tr[u<<1|1].lmx1=tr[u<<1|1].rmx1=0;
			tr[u<<1|1].mx0=tr[u<<1|1].lmx0=tr[u<<1|1].rmx0=tr[u<<1|1].r-tr[u<<1|1].l+1;
			tr[u<<1|1].tag=0;
		}
		if(tr[u].tag==1){
			tr[u<<1].sum=tr[u<<1].mx1=tr[u<<1].lmx1=tr[u<<1].rmx1=tr[u<<1].r-tr[u<<1].l+1;
			tr[u<<1].mx0=tr[u<<1].lmx0=tr[u<<1].rmx0=0;
			tr[u<<1].tag=1;

			tr[u<<1|1].sum=tr[u<<1|1].mx1=tr[u<<1|1].lmx1=tr[u<<1|1].rmx1=tr[u<<1|1].r-tr[u<<1|1].l+1;
			tr[u<<1|1].mx0=tr[u<<1|1].lmx0=tr[u<<1|1].rmx0=0;
			tr[u<<1|1].tag=1;
		}
		tr[u].tag=-1;
	}
	if(tr[u].rev){
		if(tr[u<<1].tag!=-1) tr[u<<1].tag^=1;
		else tr[u<<1].rev^=1;
		if(tr[u<<1|1].tag!=-1) tr[u<<1|1].tag^=1;
		else tr[u<<1|1].rev^=1;
		tr[u<<1].sum=tr[u<<1].r-tr[u<<1].l+1-tr[u<<1].sum;
        swap(tr[u<<1].mx0,tr[u<<1].mx1);
        swap(tr[u<<1].lmx0,tr[u<<1].lmx1);
		swap(tr[u<<1].rmx0,tr[u<<1].rmx1);

        tr[u<<1|1].sum=tr[u<<1|1].r-tr[u<<1|1].l+1-tr[u<<1|1].sum;
        swap(tr[u<<1|1].mx0,tr[u<<1|1].mx1);
        swap(tr[u<<1|1].lmx0,tr[u<<1|1].lmx1);
        swap(tr[u<<1|1].rmx0,tr[u<<1|1].rmx1);

		tr[u].rev=0;
	}
}

void build(int u,int l,int r){
	if(l==r){
		tr[u]={l,r,-1,0,a[l],1-a[l],1-a[l],1-a[l],a[l],a[l],a[l]};
		return;
	}
	tr[u]={l,r,-1,0,0,0,0,0,0,0,0};
	int mid=(l+r)>>1;
	build(u<<1,l,mid);
	build(u<<1|1,mid+1,r);
	push_up(u);
}

void update(int u,int L,int R,int k){
	if(tr[u].l>=L && tr[u].r<=R){
		if(k==0){
			tr[u].sum=tr[u].mx1=tr[u].lmx1=tr[u].rmx1=0;
			tr[u].mx0=tr[u].lmx0=tr[u].rmx0=tr[u].r-tr[u].l+1;
			tr[u].tag=0;
			tr[u].rev=0;
		}
		else if(k==1){
			tr[u].sum=tr[u].mx1=tr[u].lmx1=tr[u].rmx1=tr[u].r-tr[u].l+1;
			tr[u].mx0=tr[u].lmx0=tr[u].rmx0=0;
			tr[u].tag=1;
			tr[u].rev=0;
		}
		else if(k==2){
			tr[u].sum=tr[u].r-tr[u].l+1-tr[u].sum;
			swap(tr[u].mx0,tr[u].mx1);
			swap(tr[u].lmx0,tr[u].lmx1);
			swap(tr[u].rmx0,tr[u].rmx1);
			tr[u].rev^=1;
			if(tr[u].tag!=-1) tr[u].tag^=1;
		}
		return;
	}
	push_down(u);
	int mid=(tr[u].l+tr[u].r)>>1;
	if(L<=mid) update(u<<1,L,R,k);
	if(R>mid) update(u<<1|1,L,R,k);
	push_up(u);
}

int query1(int u,int L,int R){
	if(tr[u].l>=L && tr[u].r<=R){
		return tr[u].sum;
	}
	push_down(u);
	int mid=(tr[u].l+tr[u].r)>>1;
	int res=0;
	if(L<=mid) res+=query1(u<<1,L,R);
	if(R>mid) res+=query1(u<<1|1,L,R);
	return res;
}

Node query2(int u,int L,int R){
    if(tr[u].l>=L && tr[u].r<=R){
		return tr[u];
    }
	push_down(u);
    int mid=(tr[u].l+tr[u].r)>>1;
	if(L<=mid && R>mid){
		Node res1,res2,res;
		res1=query2(u<<1,L,R);
		res2=query2(u<<1|1,L,R);
		if(res1.mx1==res1.r-res1.l+1) res.lmx1=res1.mx1+res2.lmx1;
		else res.lmx1=res1.lmx1;
		if(res2.mx1==res2.r-res2.l+1) res.rmx1=res1.rmx1+res2.mx1;
		else res.rmx1=res2.rmx1;
		res.mx1=max({res1.mx1,res2.mx1,res1.rmx1+res2.lmx1});
		return res;
	}	
	else if(L<=mid) return query2(u<<1,L,R);
	else if(R>mid) return query2(u<<1|1,L,R);
}

int main(){
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
	}
	build(1,1,n);
	while(m--){
		int op,l,r;
		scanf("%d %d %d",&op,&l,&r);
		l++,r++;
		if(op==0){
			update(1,l,r,0);
		}
		else if(op==1){
			update(1,l,r,1);
		}
		else if(op==2){
			update(1,l,r,2);
		}
		else if(op==3){
			printf("%dn",query1(1,l,r));
		}
		else if(op==4){
			printf("%dn",query2(1,l,r).mx1);
		}
	}
    return 0;
}


程序员灯塔
转载请注明原文链接:【洛谷】 P2572 [SCOI2010]序列操作 (线段树)
喜欢 (0)