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;

}

 

你可能感兴趣的:(HDU)