hdu 3308(线段树区间合并)

本文介绍了一种基于线段树的数据结构实现——区间并,用于解决特定类型的区间操作问题。通过详细的代码解析,读者可以了解到如何利用线段树进行区间合并及查询最大连续区间的长度。文章适用于有一定数据结构基础的学习者。

线段树的区间并,这道题是比较简单的一个,,重点是细节的处理


#include<bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define sf scanf
#define pf printf
#define mem(a,b) memset(a,b,sizeof(a));
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define MP make_pair
#define ULL unsigned long long
#define LL   long long
#define inf 0x3f3f3f3f
#define md ((ll[i]+rr[i])>>1)
#define ls (i<<1)
#define rs (ls|1)
#define eps 1e-5
#define N 200050
#define ree freopen("in.txt","r",stdin);
#define bug pf("----------------");
//2017年09月25日21:29:24

int ll[N<<2],rr[N<<2],a[N],lx[N<<2],rx[N<<2],mx[N<<2];
int n,m;
int len(int i){
    return rr[i]-ll[i]+1;
}

void up(int i){
    mx[i]=max(mx[ls],mx[rs]);
    if(a[md]<a[md+1]){
        mx[i]=max(mx[i],rx[ls]+lx[rs]);
        if(lx[ls]==len(ls))
            lx[i]=len(ls)+lx[rs];
        else
            lx[i]=lx[ls];
        if(rx[rs]==len(rs))
            rx[i]=len(rs)+rx[ls];
        else
            rx[i]=rx[rs];
    }
    else{
        lx[i]=lx[ls],rx[i]=rx[rs];
    }
}

void build(int l,int r,int i){
    ll[i]=l,rr[i]=r;
    if(l==r){
        mx[i]=lx[i]=rx[i]=1;
        return ;
    }
    build(l,md,ls);build(md+1,r,rs);
    up(i);
}

void update(int p,int val,int i){
    if(ll[i]==rr[i])return ;
    if(p<=md)
        update(p,val,ls);
    else
        update(p,val,rs);
    up(i);
}
int query(int l,int r,int i){
    if(ll[i]==l&&rr[i]==r)
        return mx[i];
    if(r<=md)return query(l,r,ls);
    if(l>md)return query(l,r,rs);
    if(a[md]>=a[md+1])
        return max(query(l,md,ls),query(md+1,r,rs));
    int ret=max(query(l,md,ls),query(md+1,r,rs));
    int head=max(l,md-rx[ls]+1);
    int tail=min(r,md+lx[rs]);
    ret=max(ret,tail-head+1);
    return ret;
}
int main(){
    //ree
    int cas;
    sf("%d",&cas);
    while(cas--){
        sf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)sf("%d",&a[i]);
        build(1,n,1);
        int k,v,l,r;
        while(m--){
            char op[2];sf("%s",op);
            if(op[0]=='Q'){
                sf("%d%d",&l,&r);
                l++;r++;
                pf("%d\n",query(l,r,1));
                continue;
            }
            sf("%d%d",&k,&v);
            k++; a[k]=v;
            update(k,v,1);
        }
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值