HDU3308LCIS(线段树区间合并)

题意:

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]. 

分析:

比较裸的线段树区间合并,做过训练指南上那道动态最大连续和(Ray,Pass me the Dishes LA3938),按照那道题的思路试着写了一下,结果很容易A掉了。另外,第一次发现scanf(“%c”,&c)会读取回车。代码可能有点丑,但是今天累了明天再总结这道题

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>

using namespace std;
const int maxn=100000+100;
struct node{
    int l,r;
}maxv[4*maxn];
int T,n,m;
int a[maxn],maxl[4*maxn],maxr[4*maxn];
node better(node a,node b){
    if((a.r-a.l)>=(b.r-b.l))
        return a;
    else
        return b;
}
void build(int o,int L,int R){
    int M=L+(R-L)/2;
    if(L==R){
        maxv[o].l=maxv[o].r=maxl[o]=maxr[o]=L;
        return ;
    }
    build(2*o,L,M);
    build(2*o+1,M+1,R);
    if(maxr[2*o+1]==M+1&&a[M+1]>a[M])
        maxr[o]=maxr[2*o];
    else
        maxr[o]=maxr[2*o+1];
    if(maxl[2*o]==M&&a[M]<a[M+1])
        maxl[o]=maxl[2*o+1];
    else
        maxl[o]=maxl[2*o];
    maxv[o]=better(maxv[2*o],maxv[2*o+1]);
    if(a[M]<a[M+1])
        maxv[o]=better(maxv[o],(node){maxr[2*o],maxl[2*o+1]});
}
int p,v;//a[p]=v;
void update(int o,int L,int R){
    int M=L+(R-L)/2;
    if(L==R){
        a[p]=v;
        return ;
    }
    if(p<=M)update(2*o,L,M);
    if(p>M)update(2*o+1,M+1,R);

    if(maxr[2*o+1]==M+1&&a[M+1]>a[M])
        maxr[o]=maxr[2*o];
    else
        maxr[o]=maxr[2*o+1];
    if(maxl[2*o]==M&&a[M+1]>a[M])
        maxl[o]=maxl[2*o+1];
    else
        maxl[o]=maxl[2*o];
    maxv[o]=better(maxv[2*o],maxv[2*o+1]);
    if(a[M]<a[M+1])
    maxv[o]=better(maxv[o],(node){maxr[2*o],maxl[2*o+1]});
}
int ql,qr;
node query(int o,int L,int R){
    node ans;
    if(ql<=L&&qr>=R){
        ans=maxv[o];
        return ans;
    }
    int M=L+(R-L)/2;
    if(ql>M)return query(2*o+1,M+1,R);
    if(qr<=M)return query(2*o,L,M);
    ans=better(query(2*o,L,M),query(2*o+1,M+1,R));
    if(a[M]<a[M+1]){
        int l=max(ql,maxr[2*o]);
        int r=min(qr,maxl[2*o+1]);
        ans=better(ans,(node){l,r});
    }
    return ans;
}
void tra(int o,int L,int R){
    cout<<L<<"->"<<R<<" "<<maxv[o].l<<" "<<maxv[o].r<<endl;
    if(L==R)
        return ;
    int M=L+(R-L)/2;
    tra(2*o,L,M);
    tra(2*o+1,M+1,R);
}

int main(){
    scanf("%d",&T);
    for(int k=1;k<=T;k++){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        build(1,1,n);
        //tra(1,1,n);
        char c;
        for(int i=1;i<=m;i++){
            scanf(" %c",&c);

            if(c=='U'){
                scanf("%d%d",&p,&v);
                p++;
                update(1,1,n);
                //tra(1,1,n);
            }
            if(c=='Q'){
                    scanf("%d%d",&ql,&qr);
                    ql++;qr++;
                    node ans=query(1,1,n);
                    cout<<ans.r-ans.l+1<<endl;
            }
           }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值