hdu 3911 Black And White 区间合并 线段树

题意:重要的是求某个区间最长的1区间。

#include<cstdio>
#include<cstring>
#define left l,m,x<<1
#define right m+1,r,x<<1|1
const int LMT=100004;
int ox[LMT<<2],lsum[2][LMT<<2],msum[2][LMT<<2],rsum[2][LMT<<2];
void init(void)
{
    memset(msum,0,sizeof(msum));
    memset(lsum,0,sizeof(lsum));
    memset(rsum,0,sizeof(rsum));
    memset(ox,0,sizeof(ox));
}
inline int max(int a,int b)
{
    return a>b?a:b;
}
void swap(int &a,int &b)
{
    int t=a;
    a=b;
    b=t;
}
void fox(int l,int r,int x)
{
    ox[x]^=1;
    swap(lsum[0][x],lsum[1][x]);
    swap(rsum[0][x],rsum[1][x]);
    swap(msum[0][x],msum[1][x]);
}
void cut(int l,int r,int x)
{
    int m=(l+r)>>1;
    if(ox[x])
    {
        fox(right);fox(left);
        ox[x]=0;
    }
}
void pushup(int pos,int x,int len)
{
    lsum[pos][x]=lsum[pos][x<<1];
    rsum[pos][x]=rsum[pos][x<<1|1];
    if(lsum[pos][x<<1]==len-(len>>1))lsum[pos][x]+=lsum[pos][x<<1|1];
    if(rsum[pos][x<<1|1]==len>>1)rsum[pos][x]+=rsum[pos][x<<1];
    msum[pos][x]=max(rsum[pos][x<<1]+lsum[pos][x<<1|1],max(msum[pos][x<<1],msum[pos][x<<1|1]));
}
void update(int L,int R,int l,int r,int x)
{
    if(L<=l&&r<=R)
    {
        fox(l,r,x);
        return;
    }
    cut(l,r,x);
    int m=(l+r)>>1;
    if(L<=m)update(L,R,left);
    if(R>m)update(L,R,right);
    pushup(0,x,r-l+1);
    pushup(1,x,r-l+1);
}
void query(int *res,int L,int R,int l,int r,int x)
{
    if(L<=l&&r<=R)
    {
        res[0]=lsum[1][x];
        res[1]=msum[1][x];
        res[2]=rsum[1][x];
        return;
    }
    int resl[3],resr[3],m=(l+r)>>1,len=r-l+1;
    memset(resl,0,sizeof(resl));
    memset(resr,0,sizeof(resr));
    cut(l,r,x);
    if(L<=m)query(resl,L,R,left);
    if(R>m)query(resr,L,R,right);
    res[0]=resl[0];res[2]=resr[2];
    if(resl[0]==len-(len>>1))res[0]+=resr[0];
    if(resr[2]==len>>1)res[2]+=resl[2];
    res[1]=max(resl[2]+resr[0],max(resl[1],resr[1]));
}
void build(int l,int r,int x)
{
    if(l==r)
    {
        int num;
        scanf("%d",&num);
        msum[1][x]=lsum[1][x]=rsum[1][x]=num;
        lsum[0][x]=msum[0][x]=rsum[0][x]=(num==0);
        return;
    }
    int m=(l+r)>>1;
    build(left);
    build(right);
    pushup(0,x,r-l+1);
    pushup(1,x,r-l+1);
}
int main(void)
{
    int n,m,op,l,r,have[3];
    while(~scanf("%d",&n))
    {
        init();
        build(0,n-1,1);
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d%d%d",&op,&l,&r);
            l--;r--;
            if(op)update(l,r,0,n-1,1);
            else
            {
                memset(have,0,sizeof(have));
                query(have,l,r,0,n-1,1);
                printf("%d\n",have[1]);
            }
        }
    }
    return 0;
}


你可能感兴趣的:(hdu 3911 Black And White 区间合并 线段树)