HDU 3308 LCIS 最长连续递增序列+数据结构+线段树+单点更新

HDU 3308 LCIS

Time Limit:2000MS    Memory Limit:32768KB    64bit IO Format:%I64d & %I64u

Description

Given n integers.
You have two operations:
U A B: replace the Ath number by B. (index counting from 0)
Q A B: output the length of the longest consecutive increasing subsequence (LCIS) in [a, b].

Input

T in the first line, indicating the case number.
Each case starts with two integers n , m(0<n,m<=10 5).
The next line has n integers(0<=val<=10 5).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=10 5)
OR
Q A B(0<=A<=B< n).

Output

For each Q, output the answer.

Sample Input

1
10 10
7 7 3 3 5 9 9 8 1 8 
Q 6 6
U 3 4
Q 0 1
Q 0 5
Q 4 7
Q 3 5
Q 0 2
Q 4 6
U 6 10
Q 0 9

Sample Output

1
1
4
2
3
1
2
5

解题思路:
最长连续递增序列,设计成线段树的题目,这种题用线段树来做就好,线段树维护:
llen[]区间左端点向右延伸的最大距离
rlen[]区间右端点向左延伸的最大距离
maxlen[]区间最大长度
一个正常的数组保存每一个位置的值
有几个地方要注意
1,区间合并的时候,判断左区间右端点小于右区间左端点即可合并,并处理llen和rlen的延伸
2,query的时候,注意当一个大区间被分为两部分的时候maxlen的值有可能就在中点m的位置
左右这时候需要拿出来处理一下

#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 100005 ;
int maxlen[maxn<<2] ;
int llen[maxn<<2] ;
int rlen[maxn<<2] ;
int arry[maxn] ;
void pushup(int l,int r,int rt){
    int m = (l+r)>>1 ;
    llen[rt] = llen[rt<<1] ;
    rlen[rt] = rlen[rt<<1|1] ;
    maxlen[rt] = max(maxlen[rt<<1],maxlen[rt<<1|1]) ;
    if(arry[m]<arry[m+1]){
        maxlen[rt] = max(rlen[rt<<1]+llen[rt<<1|1] ,maxlen[rt]);
        if(llen[rt<<1] == m-l+1){
            llen[rt] = llen[rt<<1]+llen[rt<<1|1] ;
        }if(rlen[rt<<1|1] == r-m){
            rlen[rt] = rlen[rt<<1|1]+rlen[rt<<1] ;
        }
    }
    return ;
}

void build(int l,int r,int rt){
    if(l==r){
        scanf("%d",&arry[l]);
        maxlen[rt] = llen[rt] = rlen[rt] = 1 ;
        return ;
    }
    int m = (l+r)>>1 ;
    build(lson) ;
    build(rson) ;
    pushup(l,r,rt) ;
    //printf("rt = %d len = %d\n",rt,maxlen[rt]);
}
void update(int p,int s,int l,int r,int rt){
    int m = (l+r)>>1 ;
    if(l==r){
        arry[l] = s ;
        return ;
    }
    if(p<=m)update(p,s,lson) ;
    else update(p,s,rson) ;
    pushup(l,r,rt) ;
}
int query(int L,int R,int l,int r,int rt){
    int ret = 1 ;
    if(L<=l&&r<=R){
        return maxlen[rt] ;
    }
    int m  = (l+r)>>1 ;
    if(arry[m]<arry[m+1])ret = max(ret,min(R,m+llen[rt<<1|1])-max(L,m+1-rlen[rt<<1])+1);
    if(L<=m)ret=max(ret,query(L,R,lson)) ;
    if(R>m)ret=max(ret,query(L,R,rson)) ;
    return ret ;
}
int n,m;
int main(){
    int T;
    //freopen("in.txt","r",stdin);
    //freopen("out2.txt","w",stdout);
    scanf("%d",&T);
    while(T--){
        //memset(setv,0,sizeof(setv)) ;
        memset(arry,0,sizeof(arry)) ;
        memset(maxlen,0,sizeof(maxlen)) ;
        memset(llen,0,sizeof(llen)) ;
        memset(rlen,0,sizeof(rlen)) ;
        scanf("%d%d",&n,&m);
        build(1,n,1) ;
        //printf("masxn = %d\n",maxlen[1]);
        while(m--){
            char op[3] ;
            int a,b;
            scanf("%s%d%d",op,&a,&b);
            if(op[0] == 'U'){
                update(a+1,b,1,n,1) ;
            }else{
                int ans = query(a+1,b+1,1,n,1) ;
                printf("%d\n",ans) ;
            }
        }
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值