hdu 3308 LCIS(单点更新+区间合并)

题意:长度为N的数组,进行m次操作,

分为两种操作:

操作1:U A B 把位置A上的更新为B,

操作2: Q A B 输出[A,B]上的最长连续上升子序列


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


思路:

操作1,:单点更新

操作2:求连续的上升子序列,区间合并,

线段树节点维护三个值,这个子序列的左边开始的个数,右边开始的个数,这个区间的子序列的个数


和poj 3368多了一点在于单点更新~~~


#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define maxn 100010
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

int n,m;
int val[maxn];

struct segnode{
    int lnum,rnum,num;
};
segnode tree[maxn<<2];

void PushUp(int rt,int l,int r){
    int m = (l + r)/2;

    tree[rt].lnum = tree[rt<<1].lnum;
    tree[rt].rnum = tree[rt<<1|1].rnum;
    tree[rt].num  = max(tree[rt<<1].num , tree[rt<<1|1].num);

    if(val[m] < val[m+1]){
        if(tree[rt<<1].lnum == (m - l + 1))
            tree[rt].lnum += tree[rt<<1|1].lnum;

        if(tree[rt<<1|1].rnum == (r - m))
            tree[rt].rnum  += tree[rt<<1].rnum;

        tree[rt].num = max(tree[rt].num,(tree[rt<<1].rnum + tree[rt<<1|1].lnum));
    }
}

void build(int l,int r,int rt){
    if(l == r){
        tree[rt].lnum = 1;
        tree[rt].rnum = 1;
        tree[rt].num  = 1;
        return ;
    }
    int m = (l + r)/2;
    build(lson);
    build(rson);
    PushUp(rt,l,r);
}

void update(int pos,int c,int l,int r,int rt){
    if(l == r){
        val[pos] = c;
        return ;
    }
    int m = (l + r)/2;
    if(pos <= m) update(pos,c,lson);
    else update(pos,c,rson);
    PushUp(rt,l,r);
}

int query(int L,int R,int l,int r,int rt){
    if(L <= l && r <= R){
        return tree[rt].num;
    }
    int m = (l + r)/2;

    if(R <= m) return query(L,R,lson);
    else if(L > m) return query(L,R,rson);
    else{
        int lans = query(L,m,lson);
        int rans = query(m+1,R,rson);
        if(val[m] < val[m+1]){
                int temp = min(tree[rt<<1].rnum ,(m - L + 1)) + min(tree[rt<<1|1].lnum , R - m);
                return max(temp,max(lans,rans));
        }
        else{
            return max(lans,rans);
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
        scanf("%d",&val[i]);

        build(1,n,1);
        while(m--){
            char op[10];
            int a,b;
            scanf("%s %d %d",op,&a,&b);
            if(op[0]=='U'){
                update(a+1,b,1,n,1);
            }
            else{
                printf("%d\n",query(a+1,b+1,1,n,1));
            }
        }
    }
    return 0;
}




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值