ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-11-25 12:35:11  阅读:149  来源: 互联网

标签:洛谷 标记 int res tr 取反 连续 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("%d\n",query1(1,l,r));
		}
		else if(op==4){
			printf("%d\n",query2(1,l,r).mx1);
		}
	}
    return 0;
}

标签:洛谷,标记,int,res,tr,取反,连续,P2572,SCOI2010
来源: https://www.cnblogs.com/lr599909928/p/15602039.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有