hdu 3397

思路:覆盖标记要有两种 当前段全部是1 当前段全部是0 当然开一个数组写也是可以的

但是!!再覆盖过程中,

要和异或标记分清楚  如果你先覆盖那么后面随便你来几个抑或标记都只要处理异或标记

但是不管当前有什么标记 只要又覆盖标记 其他标记就都没有了

因此在向下更新的过程中 要逆次序进行 也就是先处理是否有覆盖标记 然后再处理抑或标记

#include<iostream>
#include<stdio.h>
#include<cstdio>
using namespace std;
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid ((l+r)>>1)
#define  maxn 222222
int l0[maxn<<2],m0[maxn<<2],r0[maxn<<2];
int l1[maxn<<2],m1[maxn<<2],r1[maxn<<2];
int lazy0[maxn<<2],lazy1[maxn<<2];
int sum[maxn<<2];
int ox[maxn<<2];
int n,m,x,a,b;
void up(int rt,int l,int r)
{
    l0[rt]=l0[ls];m0[rt]=max(m0[ls],m0[rs]);r0[rt]=r0[rs];
    l1[rt]=l1[ls];m1[rt]=max(m1[ls],m1[rs]);r1[rt]=r1[rs];
    
    if(l0[ls]==(mid-l+1))
        l0[rt]+=l0[rs];
    if(l1[ls]==(mid-l+1))
        l1[rt]+=l1[rs];
    if(r0[rs]==(r-mid))
        r0[rt]+=r0[ls];
    if(r1[rs]==(r-mid))
        r1[rt]+=r1[ls];

    
    m0[rt]=max(r0[ls]+l0[rs],m0[rt]);
    m1[rt]=max(r1[ls]+l1[rs],m1[rt]);
    
    sum[rt]=sum[ls]+sum[rs];
}
void build(int rt,int l,int r)
{
    ox[rt]=lazy0[rt]=lazy1[rt]=-1;
    sum[rt]=0;
    if(l==r)
    {
        scanf("%d",&x);
        sum[rt]=l1[rt]=r1[rt]=m1[rt]=x;
        l0[rt]=r0[rt]=m0[rt]=x^1;
        return ;
    }
    build(ls,l,mid);
    build(rs,mid+1,r);
    up(rt,l,r);
}
void down(int rt,int l,int r)//0 1 ox
{
    if(lazy0[rt]!=-1){
        
        lazy0[ls]=lazy0[rs]=lazy0[rt]; lazy0[rt]=-1;
        
        lazy1[ls]=lazy1[rs]=-1;
        ox[ls]=ox[rs]=-1;
        sum[ls]=sum[rs]=0;
        
        m0[ls]=l0[ls]=r0[ls]=mid-l+1;
        m0[rs]=l0[rs]=r0[rs]=r-mid;
        
        m1[ls]=l1[ls]=r1[ls]=0;
        m1[rs]=l1[rs]=r1[rs]=0;
        
        
    }
    if(lazy1[rt]!=-1){
        
        lazy1[ls]=lazy1[rs]=lazy1[rt]; lazy1[rt]=-1;
        
        lazy0[ls]=lazy0[rs]=-1;
        ox[ls]=ox[rs]=-1;
        sum[ls]=(mid-l+1);
        sum[rs]=r-mid;
        
        m1[ls]=r1[ls]=l1[ls]=mid-l+1;
        m1[rs]=r1[rs]=l1[rs]=r-mid;
        
        m0[ls]=l0[ls]=r0[ls]=0;
        m0[rs]=l0[rs]=r0[rs]=0;
        
        
    }
    if(ox[rt]!=-1)
    {
        ox[ls]=(ox[ls]==-1?1:-1);
        ox[rs]=(ox[rs]==-1?1:-1);
        ox[rt]=-1;
        
        swap(l0[ls],l1[ls]);
        swap(r0[ls],r1[ls]);
        
        swap(l0[rs],l1[rs]);
        swap(r0[rs],r1[rs]);
        
        swap(m0[ls],m1[ls]);
        swap(m0[rs],m1[rs]);
        
        sum[ls]=(mid-l+1)-sum[ls];
        sum[rs]=(r-mid)-sum[rs];
    }
}
void insox(int rt,int l,int r,int L,int R)
{
    if(L<=l&&r<=R){
        ox[rt]=(ox[rt]==1?-1:1);
        swap(l0[rt],l1[rt]);
        swap(r0[rt],r1[rt]);
        swap(m0[rt],m1[rt]);
        sum[rt]=(r-l+1)-sum[rt];
        return ;
    }
    down(rt,l,r);
    if(L<=mid)insox(ls,l,mid,L,R);
    if(mid<R)insox(rs,mid+1,r,L,R);
    up(rt,l,r);
}
void ins0(int rt,int l,int r,int L,int R){
    if(L<=l&&r<=R){
        m0[rt]=l0[rt]=r0[rt]=(r-l+1);
        m1[rt]=l1[rt]=r1[rt]=0;
        
        lazy0[rt]=1;
        ox[rt]=-1;
        lazy1[rt]=-1;
        
        sum[rt]=0;
        return ;
    }
    down(rt,l,r);
    if(L<=mid)ins0(ls,l,mid,L,R);
    if(mid<R)ins0(rs,mid+1,r,L,R);
    up(rt,l,r);
}
void ins1(int rt,int l,int r,int L,int R){
    if(L<=l&&r<=R){
        m1[rt]=l1[rt]=r1[rt]=(r-l+1);
        m0[rt]=l0[rt]=r0[rt]=0;
        
        ox[rt]=-1;
        lazy1[rt]=1;
        lazy0[rt]=-1;
        
        sum[rt]=(r-l+1);
        return ;
    }
    down(rt,l,r);
    if(L<=mid)ins1(ls,l,mid,L,R);
    if(mid<R)ins1(rs,mid+1,r,L,R);
    up(rt,l,r);
}

int tmp,tmpl,tmpr;
int querys(int rt,int l,int r,int L,int R){
    if(L<=l&&r<=R){
        return sum[rt];
    }
    int ans=0;
    down(rt,l,r);
    if(L<=mid)ans+=querys(ls,l,mid,L,R);
    if(mid<R)ans+=querys(rs,mid+1,r,L,R);
    return ans;
}
int query(int rt,int l,int r,int L,int R)
{
    if(L<=l&&r<=R)
        return m1[rt];
    down(rt,l,r);
    if(mid>=R)tmp=query(ls,l,mid,L,R);
    else if(mid<L)tmp=query(rs,mid+1,r,L,R);
    else{
        tmp=max(query(ls,l,mid,L,R),query(rs,mid+1,r,L,R));
        tmpl=min(mid-L+1,r1[ls]);
        tmpr=min(R-mid,l1[rs]);
        tmp=max(tmp,tmpl+tmpr);
    }
    return tmp;
}
void gao()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        build(1,1,n);
        while(m--){
            scanf("%d%d%d",&x,&a,&b);
              a++; b++;
            if(x==0){
                ins0(1,1,n,a,b);
            }
            else if(x==1){
                ins1(1,1,n,a,b);
            }
            else if(x==2){
                insox(1,1,n,a,b);
            }
            else if(x==3){
                printf("%d\n",querys(1,1,n,a,b));
            }
            else if(x==4){
                printf("%d\n",query(1,1,n,a,b));
            }
        }
    }
}
int main()
{
    gao();
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值