HDOJ 3911 Black And White

本文介绍了一种基于线段树的数据结构实现方法,重点解决区间合并问题。通过具体实例和代码,详细讲解了线段树如何进行区间更新与查询操作,适用于ACM竞赛和算法实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3911

此题也是属于线段树的区间合并问题,其实就是一个单纯的区间合并问题,有关线段树区间合并问题,大家可以看一道小编写的更基础的题POJ 3667 Hotel(其实这道题也是蛮基础的)。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn = 1000000+5;
int wsum[maxn<<2],lwsum[maxn],rwsum[maxn];
int bsum[maxn<<2],lbsum[maxn],rbsum[maxn];
int lazy[maxn];
int num[maxn];
void PushUp(int m,int rt)
{
    lwsum[rt]=lwsum[rt<<1];
    lbsum[rt]=lbsum[rt<<1];
    rwsum[rt]=rwsum[rt<<1|1];
    rbsum[rt]=rbsum[rt<<1|1];

    if(lwsum[rt] == m-(m>>1)) lwsum[rt] += lwsum[rt<<1|1];
    if(lbsum[rt] == m-(m>>1)) lbsum[rt] += lbsum[rt<<1|1];
    
    if(rwsum[rt] == (m>>1)) rwsum[rt]+=rwsum[rt<<1];
    if(rbsum[rt] == (m>>1)) rbsum[rt]+=rbsum[rt<<1];

    wsum[rt] = max(wsum[rt<<1],wsum[rt<<1|1]);
    bsum[rt]=max(bsum[rt<<1],bsum[rt<<1|1]);
    wsum[rt] = max(wsum[rt], rwsum[rt<<1] + lwsum[rt<<1|1]);
    bsum[rt] = max(bsum[rt], rbsum[rt<<1] + lbsum[rt<<1|1]);
}
void Change(int rt)
{
    swap(bsum[rt],wsum[rt]);
    swap(lwsum[rt],lbsum[rt]);
    swap(rwsum[rt],rbsum[rt]);
}
void PushDown(int rt)
{
    if(lazy[rt])
	{
        lazy[rt<<1]^=1;
        lazy[rt<<1|1]^=1;
        lazy[rt]=0;
        Change(rt<<1);
        Change(rt<<1|1);
    }
}
void Build(int l,int r,int rt)
{
    lazy[rt] = lbsum[rt] = rbsum[rt] = lwsum[rt] = rwsum[rt] = bsum[rt] = wsum[rt]=0;
    if(l==r)
	{
        if(num[l]==1) bsum[rt] = lbsum[rt] = rbsum[rt] = 1;
        else wsum[rt] = lwsum[rt] = rwsum[rt] = 1;
        return ;
    }
    int mid = (l+r)>>1;
    Build(lson);
    Build(rson);
    PushUp(r-l+1,rt);
}
void Update(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
	{
        lazy[rt]^=1;
        Change(rt);
        return ;
    }
    PushDown(rt);
    int mid=(l+r)>>1;
    if(L<=mid) Update(L,R,lson);
    if(R>mid) Update(L,R,rson);
    PushUp(r-l+1,rt);
}
int Query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
        return bsum[rt];
    PushDown(rt);
    int mid = (l+r)>>1;
    if( R <= mid ) 
        return Query(L, R, lson);
    if( L > mid )
        return Query(L, R, rson);
    int t1 = Query(L, R, lson);
    int t2 = Query(L, R, rson);
    int a = min(mid-L+1, rbsum[rt<<1]);
    int b = min(R-mid, lbsum[rt<<1|1]);
    return max(max(t1, t2), a + b);
}
int main(){
    int n,m,i,j,k,a,b,op;
    while(scanf("%d",&n)!=EOF)
	{
        for(i=1;i<=n;i++) scanf("%d",&num[i]);
        Build(1,n,1);
        scanf("%d",&m);
        while(m--)
		{
            scanf("%d%d%d",&op,&a,&b); 
            if(op==1) 
                Update(a,b,1,n,1);
            else
			{
                int ans=Query(a,b,1,n,1);
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值