HDU3308(LCIS) 线段树好题

Posted Kurokey

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU3308(LCIS) 线段树好题相关的知识,希望对你有一定的参考价值。

题目链接:传送门

题目大意:给你n个数,m个操作。操作有两种:1.U x y 将数组第x位变为y   2. Q x y 问数组第x位到第y位连续最长子序列的长度。对于每次询问,输出一个答案

题目思路:线段树单点修改区间合并

     这道题题目好在对pushup的理解,我们在向上更新的时候有注意情况的区分

     1.如果左区间的最右边的值小于右区间最左边的值,则有一个待定答案是左儿子的右区间+右儿子的左区间

     2.如果不符合第一个条件,则有一个待定答案是左区间最大值和右区间最大值中较大的那一个。

     有一点要特别注意:如果当前区间中所有的值都符合上升序列,那么更新它的父节点时,它可以加上其他区间的边界值而进行扩充

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <cctype>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <climits>
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define fi first
#define se second
#define ping(x,y) ((x-y)*(x-y))
#define mst(x,y) memset(x,y,sizeof(x))
#define mcp(x,y) memcpy(x,y,sizeof(y))
using namespace std;
#define gamma 0.5772156649015328606065120
#define MOD 1000000007
#define inf 0x3f3f3f3f
#define N 100005
#define maxn 50005
typedef pair<int,int> PII;
typedef long long LL;
const double pi=acos(-1.0);
const double e=2.718281828459;

int n,m,k,x,y;
int no[N<<2],ls[N<<2],rs[N<<2];
int a[N];
inline void pushup(int rt,int l,int r){
    int mid=l+r>>1;
    ls[rt]=ls[rt<<1];rs[rt]=rs[rt<<1|1];
    no[rt]=max(no[rt<<1],no[rt<<1|1]);
    if(a[mid]<a[mid+1]){
        if(ls[rt]==mid-l+1)ls[rt]+=ls[rt<<1|1];
        if(rs[rt]==r-mid)rs[rt]+=rs[rt<<1];
        no[rt]=max(no[rt],ls[rt<<1|1]+rs[rt<<1]);
    }
}
void build(int rt,int l,int r){
    if(l==r){
        no[rt]=ls[rt]=rs[rt]=1;
        return;
    }
    int mid=l+r>>1;
    build(lson);build(rson);
    pushup(rt,l,r);
}
void add(int rt,int l,int r){
    if(l==r){return;}
    int mid=l+r>>1;
    if(x<=mid)add(lson);
    else add(rson);
    pushup(rt,l,r);
}
int query(int rt,int l,int r){
    if(x<=l&&r<=y)return no[rt];
    int mid=l+r>>1;
    if(y<=mid)return query(lson);
    if(x>mid)return query(rson);
    int t1=query(lson);
    int t2=query(rson);
    int ans=max(t1,t2);
    if(a[mid]<a[mid+1]){
        ans=max(ans,(min(ls[rt<<1|1],y-mid)+min(rs[rt<<1],mid+1-x)));
    }
    return ans;
}
int main(){
    int i,j,group;
    scanf("%d",&group);
    while(group--){
        char str[5];
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;++i)scanf("%d",&a[i]);
        build(1,1,n);
        while(m--){
            scanf("%s%d%d",str,&x,&y);
            ++x;
            if(str[0]==U){a[x]=y;add(1,1,n);}
            else{++y;printf("%d\n",query(1,1,n));}
        }
    }
    return 0;
}

 

以上是关于HDU3308(LCIS) 线段树好题的主要内容,如果未能解决你的问题,请参考以下文章

hdu--3308 LCIS(线段树+区间合并)

HDU 3308 LCIS (线段树区间合并)

HDU 3308 LCIS (经典区间合并)线段树

hdu 3308 LCIS(线段树区间合并)

HDU 3308 LCIS 线段树 区间更新

hdu3308—LCIS