• 【洛谷】 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;
    }
    
    
  • 相关阅读:
    移动应用滑动屏幕方向判断解决方案,JS判断手势方向
    M1808本地配置IP全过程
    嵌入式板子tftpd交叉编译及使用
    七牛云ARM64交叉编译流程
    记录M1808Ubuntu18.04固定IP配置方案
    so库移植记录
    c++ 动态库的编译
    Linux提示Syntax error: end of file unexpected (expecting "then") 提示错误
    ubuntu18.04设置静态ip
    WebFlux中thymeleaf视图找不到的问题解决
  • 原文地址:https://www.cnblogs.com/lr599909928/p/15602039.html
Copyright © 2020-2023  润新知