hdu 3911Black And White

题意:给定一个只包含0和1的字符串,每次操作将指定区间中的0变为1,1变为0,求指定区间最长连续1的长度;

思路:线段树区间异或,成段更新;

#include<cstdio>
#include<cstring>
#include<algorithm>
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
int sum[500010],lazy[500010];
int preb[500010],prew[500010],mb[500010],subb[500010],subw[500010],mw[500010];//区间前缀1的个数、0的个数,中间1的最大个数,区间后缀1的个数、0的个数,中间最多0的个数;
void pushup(int rt,int m)
{
    preb[rt]=preb[lson];
    prew[rt]=prew[lson];
    if(preb[lson]==m-(m>>1)) preb[rt]+=preb[rson];//左区间前缀中1的个数满时,加上右区间的前缀1的个数,向上更新
    if(prew[lson]==m-(m>>1)) prew[rt]+=prew[rson];
    subb[rt]=subb[rson];
    subw[rt]=subw[rson];
    if(subb[rson]==(m>>1)) subb[rt]+=subb[lson];
    if(subw[rson]==(m>>1)) subw[rt]+=subw[lson];
    mb[rt]=max(mb[lson],mb[rson]);
    mb[rt]=max(mb[rt],subb[lson]+preb[rson]);
    mw[rt]=max(mw[lson],mw[rson]);
    mw[rt]=max(mw[rt],subw[lson]+prew[rson]);
}
void flap(int rt)
{
    swap(preb[rt],prew[rt]);
    swap(subb[rt],subw[rt]);
    swap(mb[rt],mw[rt]);
}
void pushdown(int rt)
{
    if(lazy[rt])
    {
        lazy[rt<<1]^=1;
        lazy[rt<<1|1]^=1;
        lazy[rt]=0;
        flap(rt<<1);
        flap(rt<<1|1);
    }
}
void build(int l,int r,int rt)
{
    int shu;
    int m=(l+r)/2;
    lazy[rt]=0;
    if(l==r)
    {
        scanf("%d",&shu);
        if(shu)
        {
            preb[rt]=subb[rt]=mb[rt]=1;
            prew[rt]=subw[rt]=mw[rt]=0;
        }
        else
        {
            preb[rt]=subb[rt]=mb[rt]=0;
            prew[rt]=subw[rt]=mw[rt]=1;
        }
        return;
    }
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushup(rt,r-l+1);
}
void update(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        lazy[rt]^=1;
        flap(rt);return;
    }
    pushdown(rt);
    int m=(l+r)/2;
    if(L<=m) update(L,R,l,m,rt<<1);
    if(m<R) update(L,R,m+1,r,rt<<1|1);
    pushup(rt,r-l+1);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        return mb[rt];
    }
    pushdown(rt);
    int t1,t2;
    int m=(l+r)/2;
    if(m>=R) return query(L,R,l,m,rt<<1);
    if(m<L) return query(L,R,m+1,r,rt<<1|1);
    t1=query(L,R,l,m,rt<<1);
    t2=query(L,R,m+1,r,rt<<1|1);
    return max(max(t1,t2),min(m-L+1,subb[lson])+min(R-m,preb[rson]));
}
int main()
{
    int T,n,m,i,j,k,p,x,y;
    int a[500010];
    while(scanf("%d",&n)!=EOF)
    {
        build(1,n,1);
            scanf("%d",&m);
            for(i=0;i<m;i++)
            {
                scanf("%d%d%d",&p,&x,&y);
                if(p) update(x,y,1,n,1);
                else printf("%d\n",query(x,y,1,n,1));
            }
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值