zoukankan      html  css  js  c++  java
  • 【洛谷】 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;
    }
    
    
  • 相关阅读:
    企业微信小程序用getImageInfo保存图片提示fail download image fail
    post提交定义传输数据格式-设置请求头content-type
    微信小程序-wxml模板页面逻辑运算
    微信小程序-页面间传参
    微信小程序-wxml标签绑定data值传参给js方法(事件传参)
    微信小程序-子组件调用父组件
    微信小程序-调用组件内方法(父组件调用子组件)
    input中number类型去掉上下箭头
    js slice 截取数组或字符串
    vue组件库小练习——目录
  • 原文地址:https://www.cnblogs.com/lr599909928/p/15602039.html
Copyright © 2011-2022 走看看