HDU 3308 LCIS(线段树区间合并)

本文介绍了一种处理最长连续上升子序列(LCIS)查询与节点值更新问题的算法实现。通过线段树结构支持区间查询和单点更新操作,有效解决了区间最大LCIS查询与节点值更新的问题。

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

题意:

有两种操作
Q a b 是询问区间 [a,b] 内最大的LCIS(最长连续上升子序列)
U a b是更新节点a的值为b

解析:

这题和 UESTC 360 Another LCIS 很像,具体的做法可以参考我的前面一篇博客

my code

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ls (o<<1)
#define rs (o<<1|1)
#define lson ls, L, M
#define rson rs, M+1, R
#define MID (L + R)>>1
using namespace std;
const int N = (int)1e5 + 10;
int lv[N<<2], rv[N<<2], setv[N<<2];
int lsum[N<<2], rsum[N<<2], msum[N<<2];
int n, m;

void pushDown(int o) {
    if(setv[o] != -1) {
        setv[ls] = setv[rs] = setv[o];
        lv[ls] = rv[ls] = setv[o];
        lv[rs] = rv[rs] = setv[o];
        lsum[ls] = rsum[ls] = msum[ls] = 1;
        lsum[rs] = rsum[rs] = msum[rs] = 1;
        setv[o] = -1;
    }
}

void pushUp(int o, int L, int R) {
    int M = MID;
    int lenL = M - L + 1, lenR = R - M;

    lv[o] = lv[ls], rv[o] = rv[rs];

    lsum[o] = lsum[ls];
    rsum[o] = rsum[rs];
    msum[o] = max(msum[ls], msum[rs]);

    int ml = rv[ls], mr = lv[rs];
    if(ml < mr) {
        if(lsum[ls] == lenL) lsum[o] += lsum[rs];
        if(rsum[rs] == lenR) rsum[o] += rsum[ls];
        msum[o] = max(msum[o], rsum[ls] + lsum[rs]);
    }
}

void build(int o, int L, int R) {
    setv[o] = -1;
    if(L == R) {
        scanf("%d", &rv[o]);
        setv[o] = lv[o] = rv[o];
        lsum[o] = rsum[o] = msum[o] = 1;
        return ;
    }
    pushDown(o);
    int M = MID;
    build(lson);
    build(rson);
    pushUp(o, L, R);
}

void modify(int o, int L, int R, int pos, int val) {
    if(L == R) {
        setv[o] = lv[o] = rv[o] = val;
        lsum[o] = rsum[o] = msum[o] = 1;
        return ;
    }
    pushDown(o);
    int M = MID;
    if(pos <= M) modify(lson, pos, val);
    else modify(rson, pos, val);
    pushUp(o, L, R);
}

int query(int o, int L, int R, int ql, int qr) {
    if(ql <= L && R <= qr) return msum[o];

    pushDown(o);
    int M = MID, ret = -1;
    if(ql <= M) ret = max(ret, query(lson, ql, qr));
    if(qr > M) ret = max(ret, query(rson, ql, qr));

    int ll, rr, ml = rv[ls], mr = lv[rs];
    if(ml < mr) {
        ll = min(M - ql + 1, rsum[ls]);
        rr = min(qr - M, lsum[rs]);
        ret = max(ret, ll + rr);
    }
    return ret;
}

char oper[10];
int main() {
    int T;
    scanf("%d", &T);

    int a, b;
    while(T--) {
        scanf("%d%d", &n, &m);
        build(1, 1, n);
        while(m--) {
            scanf("%s%d%d", oper, &a, &b);
            if(oper[0] == 'Q')
                printf("%d\n", query(1, 0, n-1, a, b));
            else
                modify(1, 0, n-1, a, b);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值