HDU3308 LCIS 线段树区间合并

               
Problem Description
Given n integers.
You have two operations:
U A B: replace the Ath number by B. (index counting from 0)
Q A B: output the length of the longest consecutive increasing subsequence (LCIS) in [a, b].
 

Input
T in the first line, indicating the case number.
Each case starts with two integers n , m(0<n,m<=10 5).
The next line has n integers(0<=val<=10 5).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=10 5)
OR
Q A B(0<=A<=B< n).
 

Output
For each Q, output the answer.
 

Sample Input
 
  
110 107 7 3 3 5 9 9 8 1 8 Q 6 6U 3 4Q 0 1Q 0 5Q 4 7Q 3 5Q 0 2Q 4 6U 6 10Q 0 9
 

Sample Output
 
  
11423125
 


Q是询问区间内最大的LCIS

U是更新节点

思路:简单的线段树区间合并题

 

#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;const int L = 111111;int n,m,s[L];struct node{    int l,r,c;//左右边界与连续的长度    int ln,rn;//左右边界的值    int ls,rs,ms,;//左右最大LCIS,和区间最大LCIS} a[L<<2];void pushup(int i){    a[i].ls = a[2*i].ls;    a[i].rs = a[2*i+1].rs;    a[i].ln = a[2*i].ln;    a[i].rn = a[2*i+1].rn;    a[i].ms = max(a[2*i].ms,a[2*i+1].ms);    if(a[2*i].rn<a[2*i+1].ln)//如果左子树的右边界值小于右子树的左边界值,要合并左子树的右边界和右子树的左边界进行计算    {        if(a[2*i].ls == a[2*i].c)            a[i].ls+=a[2*i+1].ls;        if(a[2*i+1].rs == a[2*i+1].c)            a[i].rs+=a[2*i].rs;        a[i].ms = max(a[i].ms,a[2*i].rs+a[2*i+1].ls);    }}void init(int l,int r,int i)//建树{    a[i].l = l;    a[i].r = r;    a[i].c = r-l+1;    if(l == r)    {        a[i].ln = a[i].rn = s[l];        a[i].ls = a[i].rs = a[i].ms = 1;        return;    }    int mid = (a[i].l+a[i].r)>>1;    init(l,mid,2*i);    init(mid+1,r,2*i+1);    pushup(i);}void insert(int i,int t,int m){    if(a[i].l == a[i].r)    {        a[i].ln = a[i].rn = m;        return;    }    int mid = (a[i].l+a[i].r)>>1;    if(t<=mid)        insert(2*i,t,m);    if(t>mid)        insert(2*i+1,t,m);    pushup(i);}int query(int l,int r,int i)//查询最大的LCIS{    if(a[i].l>=l && a[i].r<=r)    {        return a[i].ms;    }    int mid = (a[i].l+a[i].r)>>1,ans = 0;    if(l<=mid)        ans = max(ans,query(l,r,2*i));    if(r>mid)        ans = max(ans,query(l,r,2*i+1));    if(a[2*i].rn < a[2*i+1].ln)        ans = max(ans , min(mid-l+1,a[2*i].rs)+min(r-mid,a[2*i+1].ls));    return ans;}int main(){    int t,i,l,r;    char str[5];    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);        for(i = 1; i<=n; i++)            scanf("%d",&s[i]);        init(1,n,1);        while(m--)        {            scanf("%s%d%d",str,&l,&r);            if(str[0] == 'Q')                printf("%d\n",query(l+1,r+1,1));            else                insert(1,l+1,r);        }    }    return 0;}


 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值