hdu 1806

题目

区间合并。

当update的时候注意所查询边界是与左右儿子的边界进行比较

代码如下:

#include<cstdio>
#include<iostream>
using namespace std;
#define maxn 100005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct node{
    int r,l;
    int mnum,msum;
    int rnum,rsum;
    int lnum,lsum;
}tree[maxn<<2];
int num[maxn],Max;

void PushUp(int rt)
{
    tree[rt].mnum=(tree[rt<<1].msum>=tree[rt<<1|1].msum)?tree[rt<<1].mnum:tree[rt<<1|1].mnum;
    tree[rt].msum=(tree[rt<<1].msum>=tree[rt<<1|1].msum)?tree[rt<<1].msum:tree[rt<<1|1].msum;
    tree[rt].lnum=tree[rt<<1].lnum;
    tree[rt].lsum=tree[rt<<1].lsum;
    tree[rt].rnum=tree[rt<<1|1].rnum;
    tree[rt].rsum=tree[rt<<1|1].rsum;
    if(tree[rt<<1].rnum==tree[rt<<1|1].lnum)
    {
        int ans=tree[rt<<1].rsum+tree[rt<<1|1].lsum;
        if(ans>tree[rt].msum)
        {
            tree[rt].msum=ans;
            tree[rt].mnum=tree[rt<<1].rnum;
        }
        if(tree[rt<<1|1].lnum==tree[rt<<1].lnum) tree[rt].lsum+=tree[rt<<1|1].lsum;
        if(tree[rt<<1].rnum==tree[rt<<1|1].rnum) tree[rt].rsum+=tree[rt<<1].rsum;
    }
}

void bulid(int l,int r,int rt)
{
    int m,ans;
    tree[rt].l=l;
    tree[rt].r=r;
    if(l==r)
    {
        tree[rt].msum=tree[rt].lsum=tree[rt].rsum=1;
        tree[rt].mnum=tree[rt].lnum=tree[rt].rnum=num[l];
        return;
    }
    m=(l+r)>>1;
    bulid(lson);
    bulid(rson);
    PushUp(rt);
}
void update(int x,int y,int rt)
{
    int l,r;
    l=tree[rt].l;
    r=tree[rt].r;
    int m,ans1,ans2;
    if(x==l && y==r)
    {
        if(tree[rt].msum>Max) Max=tree[rt].msum;
        return;
    }


    if(y<=tree[rt<<1].r) update(x,y,rt<<1);
    else if(x>=tree[rt<<1|1].l) update(x,y,rt<<1|1);
    else
    {
        m=tree[rt<<1].r;
        update(x,m,rt<<1);
        update(m+1,y,rt<<1|1);
        if(tree[rt<<1].rnum == tree[rt<<1|1].lnum)
        {
            if(num[x]!=tree[rt<<1].rnum) ans1=tree[rt<<1].rsum;
            else ans1=m-x+1;
            if(num[y]!=tree[rt<<1|1].lnum) ans2=tree[rt<<1|1].lsum;
            else ans2=y-m;
            if(ans1+ans2 > Max) Max=ans1+ans2;
        }
    }
}
int main()
{
    int i,m,a,b,n;
    while(scanf("%d",&n)&& n)
    {
        scanf("%d",&m);
        for(i=1;i<=n;i++)
            scanf("%d",&num[i]);
        bulid(1,n,1);
        while(m--)
        {
            scanf("%d%d",&a,&b);
            if(a==b) {printf("1\n");continue;}
            Max=0;
            update(a,b,1);

            printf("%d\n",Max);
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值