zoukankan      html  css  js  c++  java
  • HDU3308–LCIS(单点修改&&区间合并)

    题目大意

    给出n个数:

    你可以对其进行以下两种操作:

    U A B: 把第A个数的值替换为B
    Q A B: 查询在区间[a, b]内的最长连续上升子序列的长度

    题解

    单点更新和区间合并

    需要维护三个域:区间LCIS长度的最值maxl,包含左端点LCIS的长度最大值lmaxl,包含右端点的LCI长度S的最大值rmaxl,合并的时候和hotel差不多,在查询区间的时候要注意,如果最长的长度是跨越了两个自区间的话,长度不能简单的认为就是rmaxl[s<<1]+lmaxl[s<<1|1],而是min(qr,m+lmaxl[s<<1|1])-max(ql,m-rmaxl[s<<1]+1)+1(ql和qr分别为当前节点的左右端点,m为中点)。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define MAXN 100005
    #define lson l,m,s<<1
    #define rson m+1,r,s<<1|1
    int maxl[MAXN<<2],lmaxl[MAXN<<2],rmaxl[MAXN<<2],val[MAXN<<2];
    void PushUp(int s,int m,int p)
    {
            lmaxl[s]=lmaxl[s<<1];
            rmaxl[s]=rmaxl[s<<1|1];
            maxl[s]=max(maxl[s<<1],maxl[s<<1|1]);
            if(val[p]<val[p+1]) {
                    if(lmaxl[s<<1]==(m-(m>>1))) lmaxl[s]+=lmaxl[s<<1|1];
                    if(rmaxl[s<<1|1]==(m>>1)) rmaxl[s]+=rmaxl[s<<1];
                    maxl[s]= max(maxl[s],rmaxl[s<<1]+lmaxl[s<<1|1]);
            }
    }
    void build(int l,int r,int s)
    {
            if(l==r) {
                    scanf("%d",&val[r]);
                    maxl[s]=lmaxl[s]=rmaxl[s]=1;
                    return;
            }
            int m=(l+r)>>1;
            build(lson);
            build(rson);
            PushUp(s,r-l+1,m);
    }
    void update(int p,int d,int l,int r,int s)
    {
            if(l==r) {
                    val[p]=d;
                    return;
            }
            int m=(l+r)>>1;
            if(p<=m) update(p,d,lson);
            else
                    update(p,d,rson);
            PushUp(s,r-l+1,m);
    }
    int query(int ql,int qr,int l,int r,int s)
    {
            if(ql<=l&&r<=qr)
                    return maxl[s];
            int m=(l+r)>>1,ans=0;
            if(ql<=m) ans=max(ans,query(ql, qr,lson));
            if(qr>m) ans=max(ans,query(ql,qr,rson));
            if(val[m]<val[m+1])
                    ans=max(ans,min(qr,m+lmaxl[s<<1|1])-max(ql,m-rmaxl[s<<1]+1)+1);
            return ans;
    }
    int main(void)
    {
            char op[5];
            int n,m,T;
            scanf("%d",&T);
            while(T--) {
                    int a,b;
                    scanf("%d%d",&n,&m);
                    build(0,n-1,1);
                    while(m--) {
                            scanf("%s",op);
                            if(op[0]=='Q') {
                                    scanf("%d%d",&a,&b);
                                    printf("%d\n",query(a,b,0,n-1,1));
                            } else {
                                    scanf("%d%d",&a,&b);
                                    update(a,b,0,n-1,1);
                            }
                    }
            }
            return 0;
    }

     

  • 相关阅读:
    PHP获取指定分钟数的下一个整数倍
    phpspreadsheet
    澳大利亚 主要城市列表
    db2编目抽取
    openssl实现CA自签证书和颁发数字证书
    基于Docker的redis集群搭建
    Python测试DB2连通性
    在Vim中查看文件编码
    搭建redis集群
    Python(十)之GUI编程
  • 原文地址:https://www.cnblogs.com/zjbztianya/p/3114524.html
Copyright © 2011-2022 走看看