HDU 3308 LCIS

最裸的求区间最大递增子序列,单点更新区间合并线段树,存下来当个模板吧

#include <cstdio>

using namespace std;

#define M ((L+R)>>1)
#define lson rt<<1,L,M
#define rson rt<<1|1,M+1,R
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define len(a,b) ((b)-(a)+1)

const int maxn = 100001;
const int sizen = maxn << 2;

int lmax[sizen],rmax[sizen],val[maxn],mmax[sizen],tar,v;

inline void pushup(int rt,int L,int R) {
    int l = rt<<1,r = rt<<1|1;
    lmax[rt] = lmax[l]; rmax[rt] = rmax[r];
    mmax[rt] = 0;
    if(val[M] < val[M + 1]) {
        if(lmax[l] == len(L,M)) lmax[rt] += lmax[r];
        if(rmax[r] == len(M + 1,R)) rmax[rt] += rmax[l];
        mmax[rt] = max(lmax[rt],rmax[rt]);
        mmax[rt] = max(mmax[rt],rmax[l] + lmax[r]);
    }
    mmax[rt] = max(mmax[rt],max(mmax[l],mmax[r]));
}

void build(int rt,int L,int R) {
    if(L == R) {
        lmax[rt] = rmax[rt] = mmax[rt] = 1;
    } else {
        build(lson); build(rson);
        pushup(rt,L,R);
    }
}

void update(int rt,int L,int R) {
    if(L == R) val[L] = v;
    else {
        if(tar <= M) update(lson);
        else update(rson);
        pushup(rt,L,R);
    }
}

int query(int rt,int L,int R,int ql,int qr) {
    if(ql == L && qr == R) return mmax[rt];
    int l = rt<<1,r = rt<<1|1;
    if(qr <= M) return query(lson,ql,qr);
    if(ql > M) return query(rson,ql,qr);
    int ans = 0,left = query(lson,ql,M),right = query(rson,M + 1,qr);
    ans = max(left,right);
    if(val[M] < val[M + 1]) ans = max(ans,min(len(ql,M),rmax[l]) + min(len(M + 1,qr),lmax[r]));
    return ans;
}

int main() {
    int T,N,Q,l,r;
    char cmd;
    scanf("%d",&T);
    for(int c = 1;c <= T;c++) {
        scanf("%d%d",&N,&Q);
        for(int i = 1;i <= N;i++) scanf("%d",val + i);
        build(1,1,N);
        for(int q = 0;q < Q;q++) {
            scanf(" %c%d%d",&cmd,&l,&r);
            l++; r++;
            if(cmd == 'Q') printf("%d\n",query(1,1,N,l,r));
            else {
                tar = l; v = r - 1;
                update(1,1,N);
            }
        }
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值