HDU 3911 (线段树,区间合并,延迟标记)

题意:就是给你一段由0和1组成的序列,然后有两种操作:0 a b就是问从a到b最长的连续的1的长度为多少,1 a b就是把 [a,b]中的1变为0,0变为1。// 进行一次反转操作,就是将区间0和1ji'l记录的数据对换。

:用一个结构体,lmaxn1表示从最左边数连续1的长度,lmaxn0表示从左边数连续0的长度,rmaxn1表示从右边数连续1的长度,rmaxn0表示从右边数连续0的长度,max0表示连续最长的0的个数,max1表示连续最长的1的个数,flag用来做延迟标记. l记录区间的左端点,r记录区间的右端点,len记录区间长度 (后面更新1的最长连续长度会用到)

#include<iostream>
using namespace std;
#define max(x,y) (x>y?x:y)
#define min(x,y) (x<y?x:y)
const int size_maxn=1e5+50;
int n,m,c;
struct node
{
    int lmaxn0;
    int rmaxn0;
    int lmaxn1;
    int rmaxn1;
    int maxn1;
    int maxn0;
    int l,r,flag,len;
}root[size_maxn*4];

void pushup(int sign)        //进行维护
{
    root[sign].lmaxn1=root[sign<<1].lmaxn1;
    if(root[sign<<1].len==root[sign<<1].lmaxn1)
        root[sign].lmaxn1+=root[sign<<1|1].lmaxn1;
    root[sign].rmaxn1=root[sign<<1|1].rmaxn1;
    if(root[sign<<1|1].len==root[sign<<1|1].rmaxn1)
        root[sign].rmaxn1+=root[sign<<1].rmaxn1;
    root[sign].lmaxn0=root[sign<<1].lmaxn0;
    if(root[sign<<1].len==root[sign<<1].lmaxn0)
        root[sign].lmaxn0+=root[sign<<1|1].lmaxn0;
    root[sign].rmaxn0=root[sign<<1|1].rmaxn0;
    if(root[sign<<1|1].len==root[sign<<1|1].rmaxn0)
        root[sign].rmaxn0+=root[sign<<1].rmaxn0;
    root[sign].maxn0=max(root[sign<<1].maxn0,root[sign<<1|1].maxn0);
    root[sign].maxn0=max(root[sign].maxn0,root[sign<<1].rmaxn0+root[sign<<1|1].lmaxn0);
    root[sign].maxn1=max(root[sign<<1].maxn1,root[sign<<1|1].maxn1);
    root[sign].maxn1=max(root[sign].maxn1,root[sign<<1].rmaxn1+root[sign<<1|1].lmaxn1);
}

void pushdown(int sign)        向下标记
{
    root[sign<<1].flag^=1;
    root[sign<<1|1].flag^=1;
    swap(root[sign<<1].lmaxn0,root[sign<<1].lmaxn1);
    swap(root[sign<<1].rmaxn0,root[sign<<1].rmaxn1);
    swap(root[sign<<1].maxn0,root[sign<<1].maxn1);
    swap(root[sign<<1|1].lmaxn0,root[sign<<1|1].lmaxn1);
    swap(root[sign<<1|1].rmaxn0,root[sign<<1|1].rmaxn1);
    swap(root[sign<<1|1].maxn0,root[sign<<1|1].maxn1);
    root[sign].flag=0;
}

void buildroot(int l,int r,int sign)            //建树
{
    root[sign].l=l;
    root[sign].r=r;
    root[sign].flag=0;
    root[sign].len=r-l+1;
    if(l==r)
    {
        scanf("%d",&c);
        if(c)
        {
            root[sign].lmaxn0=0;
            root[sign].rmaxn0=0;
            root[sign].maxn0=0;
            root[sign].lmaxn1=1;
            root[sign].rmaxn1=1;
            root[sign].maxn1=1;
        }
        else
        {
            root[sign].lmaxn0=1;
            root[sign].rmaxn0=1;
            root[sign].maxn0=1;
            root[sign].lmaxn1=0;
            root[sign].rmaxn1=0;
            root[sign].maxn1=0;
        }
        return ;
    }
    int mid=l+r>>1;
    buildroot(l,mid,sign<<1);
    buildroot(mid+1,r,sign<<1|1);
    pushup(sign);
}

void update(int l,int r,int sign)        //跟新区间
{
    if(root[sign].l==l&&root[sign].r==r)
    {
        swap(root[sign].lmaxn0,root[sign].lmaxn1);
        swap(root[sign].rmaxn0,root[sign].rmaxn1);
        swap(root[sign].maxn0,root[sign].maxn1);
        root[sign].flag^=1;
        return ;
    }
    if(root[sign].flag==1)
        pushdown(sign);
    int mid=root[sign].l+root[sign].r>>1;
    if(r<=mid)
        update(l,r,sign<<1);
    else if(l>mid)
        update(l,r,sign<<1|1);
    else
    {
        update(l,mid,sign<<1);
        update(mid+1,r,sign<<1|1);
    }
    pushup(sign);
}

int findroot(int l,int r,int sign)        //寻找区间1的最长长度
{
    if(root[sign].l==l&&root[sign].r==r)
        return root[sign].maxn1;
    int mid=root[sign].l+root[sign].r>>1;
    if(root[sign].flag==1)
        pushdown(sign);
    if(r<=mid)
        return findroot(l,r,sign<<1);
    else if(mid<l)
        return findroot(l,r,sign<<1|1);
    else
    {
        int aa,bb,cc;
        aa=min(mid-l+1,root[sign<<1].rmaxn1)+min(r-mid,root[sign<<1|1].lmaxn1);
        bb=findroot(l,mid,sign<<1);
        cc=findroot(mid+1,r,sign<<1|1);
        return max(aa,max(bb,cc));
    }
}

int main()
{
    while(~scanf("%d",&n))
    {
        buildroot(1,n,1);
        scanf("%d",&m);
        while(m--)
        {
            int step,a,b;
            scanf("%d %d %d",&step,&a,&b);
            if(step)
                update(a,b,1);
            else
                printf("%d\n",findroot(a,b,1));
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42211531/article/details/81297470