hdu3308LCIS 线段树

//U A B 将第A位置的元素改为B
//Q A B询问[A , B]区间的最长的递增序列
//维护ma_l , ma , ma_r 左边最长,区间最长,右边最长
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std ;
const int maxn = 1e5 + 10 ;
#define left v<<1
#define right v<<1|1
struct node
{
    int l , r ;
    int ma_l , ma_r , ma ;
}tree[maxn<<2] ;
int h[maxn] ;
int T ;
int n , m ;
void push_up(int v)
{
    tree[v].ma_l = tree[left].ma_l ;
    tree[v].ma_r = tree[right].ma_r ;
    tree[v].ma = max(tree[left].ma , tree[right].ma) ;
    if(h[tree[left].r] < h[tree[right].l])
    {
        tree[v].ma = max(tree[v].ma , tree[left].ma_r + tree[right].ma_l) ;
        if(tree[left].r - tree[left].l + 1 == tree[v].ma_l)
        tree[v].ma_l += tree[right].ma_l ;
        if(tree[right].r - tree[right].l + 1 == tree[v].ma_r)
        tree[v].ma_r += tree[left].ma_r ;
    }
}
void build(int l , int r , int v)
{
    tree[v].l = l ;
    tree[v].r = r;
    if(l == r)
    {
        tree[v].ma_l = tree[v].ma = tree[v].ma_r = 1 ;
        return ;
    }
    int mid = (l + r) >> 1 ;
    build(l , mid , left) ;
    build(mid + 1 , r , right) ;
    push_up(v) ;
}
int query(int v , int l , int r)
{

    if(l <= tree[v].l && tree[v].r <= r)
    return tree[v].ma ;
    int mid = (tree[v].l + tree[v].r) >> 1 ;
    int ans_1 = 0 , ans_2 = 0 ,ans_3 = 0 ;
    if(l <= mid)ans_1 = query(left , l , r) ;
    if(r > mid)ans_2 = query(right , l , r) ;
    int ans = max(ans_1 , ans_2) ;
    if(h[tree[left].r] < h[tree[right].l])
    {
        ans_3 = min(tree[left].ma_r , tree[left].r - l + 1) + min(tree[right].ma_l , r - tree[right].l + 1) ;
        ans = max(ans , ans_3) ;
    }
    return ans ;
}
void update(int pos , int num ,int v)
{
    if(tree[v].l == tree[v].r)
    {
        h[pos] = num ;
        return  ;
    }
    int mid = (tree[v].l + tree[v].r) >> 1 ;
    if(pos <= mid)update(pos , num , left);
    else if(pos > mid)update(pos ,num ,right) ;
    push_up(v) ;
}
int main()
{
   // freopen("in.txt" ,"r" ,stdin) ;
    scanf("%d" , &T) ;
    while(T--)
    {
        scanf("%d%d" ,&n , &m) ;
        for(int i = 1;i <= n;i++)
        scanf("%d" , &h[i]) ;
        build(1 , n , 1) ;
        char ch[10] ;int a , b ;
        while(m--)
        {
            scanf("%s" ,ch) ;
            scanf("%d%d" ,&a , &b) ;
            if(ch[0] == 'Q')
            printf("%d\n" ,query(1 , a  + 1, b + 1));
            else if(ch[0] == 'U')
            update(a+1 , b , 1) ;
        }
    }
    return 0 ;
}

你可能感兴趣的:(线段树)