HDU 3397 线段树 较麻烦

3911的升级版

同时要做两种LAZY操作,一定要先做COVER,否则会WA,因为COVER可以覆盖之前的XOR

 

#include "stdio.h"
#include "string.h"
#include "math.h"
#include "stdlib.h"
#include "algorithm"
using namespace std;

struct comp
{
    int l,r,mid;
    int l1,l0; // 记录区间内从最左端起连续1和0个数
    int r1,r0; // 记录区间内从最右端起连续1和0个数
    int m1,m0; // 记录区间内最长连续1和0个数
    int cover; // lazy操作的覆盖
    int xor; // lazy操作的变换
    int sum; // 区间内1的总数
} data[300005];


int max(int a,int b)
{
    if (a<b) return b; else return a;
}
void PushUp(int k)
{
    int ll,rr;
    ll=data[k*2].r-data[k*2].l+1;
    rr=data[k*2+1].r-data[k*2+1].l+1;

    data[k].sum=data[k*2].sum+data[k*2+1].sum;

    data[k].l1=data[k*2].l1;
    if (data[k].l1==ll) data[k].l1+=data[k*2+1].l1;
    data[k].l0=data[k*2].l0;
    if (data[k].l0==ll) data[k].l0+=data[k*2+1].l0;

    data[k].r1=data[k*2+1].r1;
    if (data[k].r1==rr) data[k].r1+=data[k*2].r1;
    data[k].r0=data[k*2+1].r0;
    if (data[k].r0==rr) data[k].r0+=data[k*2].r0;

    data[k].m1=max(  max(data[k*2].m1,data[k*2+1].m1) ,  data[k*2].r1+data[k*2+1].l1);
    data[k].m0=max(  max(data[k*2].m0,data[k*2+1].m0) ,  data[k*2].r0+data[k*2+1].l0);
}



void build(int l,int r,int k)
{
    int x;
    data[k].l=l; data[k].r=r;
    data[k].mid=(l+r)/2;
    data[k].xor=0;
    data[k].cover=-1;
    
    if (l==r)
    {
        scanf("%d",&x);
        if (x==1)
        {
            data[k].l1=data[k].r1=data[k].m1=1;
            data[k].l0=data[k].r0=data[k].m0=0;
            data[k].sum=1;
            data[k].cover=1;
        }
        else 
        {
            data[k].l1=data[k].r1=data[k].m1=0;
            data[k].l0=data[k].r0=data[k].m0=1;
            data[k].sum=0;
            data[k].cover=0;
        }
        return ;
    }

    build(l,data[k].mid,k*2);
    build(data[k].mid+1,r,k*2+1);

    PushUp(k);
}

void PushDown(int k) // 重点是两种LAZY操作的顺序,必须先做COVER操作
{
    int ll,rr;
    if (data[k].l==data[k].r) return ;
    ll=data[k*2].r-data[k*2].l+1;
    rr=data[k*2+1].r-data[k*2+1].l+1;


    if (data[k].cover!=-1)
    {
        data[k*2].cover=data[k*2+1].cover=data[k].cover;
        data[k*2].xor=data[k*2+1].xor=0;
        if (data[k].cover==1)
        {
            data[k*2].sum=ll;
            data[k*2+1].sum=rr;
            
            data[k*2].l1=data[k*2].r1=data[k*2].m1=ll;
            data[k*2].l0=data[k*2].r0=data[k*2].m0=0;

            data[k*2+1].l1=data[k*2+1].r1=data[k*2+1].m1=rr;
            data[k*2+1].l0=data[k*2+1].r0=data[k*2+1].m0=0;
        }
        if (data[k].cover==0)
        {
            data[k*2].sum=data[k*2+1].sum=0;

            data[k*2].l1=data[k*2].r1=data[k*2].m1=0;
            data[k*2].l0=data[k*2].r0=data[k*2].m0=ll;

            data[k*2+1].l1=data[k*2+1].r1=data[k*2+1].m1=0;
            data[k*2+1].l0=data[k*2+1].r0=data[k*2+1].m0=rr;
        }
        data[k].cover=-1;
    }

	
	if (data[k].xor%2==1)
    {
        data[k].xor=0;
        data[k*2].xor++;
        data[k*2+1].xor++;

        data[k*2].sum=ll-data[k*2].sum;
        data[k*2+1].sum=rr-data[k*2+1].sum;

        swap(data[k*2].l1,data[k*2].l0);
        swap(data[k*2].r1,data[k*2].r0);
        swap(data[k*2].m1,data[k*2].m0);

        swap(data[k*2+1].l1,data[k*2+1].l0);
        swap(data[k*2+1].r1,data[k*2+1].r0);
        swap(data[k*2+1].m1,data[k*2+1].m0);

    }

    
}

    

void update(int l,int r,int k,int op)
{
    int le;
    PushDown(k);
    if (data[k].l==l && data[k].r==r )
    {
        le=data[k].r-data[k].l+1;
        if (op==0)
        {
            data[k].cover=0;
            data[k].sum=0;
            data[k].l1=data[k].r1=data[k].m1=0;
            data[k].l0=data[k].r0=data[k].m0=le;
            data[k].xor=0;
        }
        if (op==1)
        {
            data[k].cover=1;
            data[k].sum=le;
            data[k].l1=data[k].r1=data[k].m1=le;
            data[k].l0=data[k].r0=data[k].m0=0;
            data[k].xor=0;
        }
        if (op==2)
        {
            if (data[k].cover!=-1) data[k].cover=(data[k].cover+1)%2;
            data[k].sum=le-data[k].sum;
            swap(data[k].l1,data[k].l0);
            swap(data[k].r1,data[k].r0);
            swap(data[k].m1,data[k].m0);
            data[k].xor++;
        }
        return ;
    }

    

    if (r<=data[k].mid) update(l,r,k*2,op);
    else 
        if (l>data[k].mid) update(l,r,k*2+1,op);
        else 
        {
            update(l,data[k].mid,k*2,op);
            update(data[k].mid+1,r,k*2+1,op);
        }

    PushUp(k);
}

int query(int l,int r,int k,int op)
{
    int aa,bb,ll,rr;
    if (data[k].l==l && data[k].r==r) 
    {
        if (op==3) return data[k].sum;
        else return data[k].m1;
    }

    PushDown(k);

    if (r<=data[k].mid) return query(l,r,k*2,op);
    else 
        if (l>data[k].mid) return query(l,r,k*2+1,op);
        else 
        {
            if (op==3) return query(l,data[k].mid,k*2,op)+query(data[k].mid+1,r,k*2+1,op);
            else 
            {
                aa=query(l,data[k].mid,k*2,op);
                bb=query(data[k].mid+1,r,k*2+1,op);

                ll=data[k*2].r1;
                if (ll>data[k*2].r-l+1) ll=data[k*2].r-l+1;

                rr=data[k*2+1].l1;
                if (rr>r-data[k*2+1].l+1) rr=r-data[k*2+1].l+1;

                return max(max(aa,bb),ll+rr);
            }
        }
}
int main()
{
    int t,n,m,a,b,c;

    scanf("%d",&t);
    while (t--)
    {
        scanf("%d%d",&n,&m);
        build(1,n,1);
        while (m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            b++;
            c++;
            if (a<=2) update(b,c,1,a);
            else 
                    printf("%d\n",query(b,c,1,a));
        }
    }
    return 0;
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值