HDU 3308 LCIS(线段树单点更新区间合并)

                                                                                               LCIS

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

1
10 10
7 7 3 3 5 9 9 8 1 8
Q 6 6
U 3 4
Q 0 1
Q 0 5
Q 4 7
Q 3 5
Q 0 2
Q 4 6
U 6 10
Q 0 9
                

Sample Output

1
1
4
2
3
1
2
5
 
题意:求区间[a,b]连续上升的最大区间长度。
解析:线段树维护以下几种信息:左右端点(le,ri),区间长度(len),左端的数(lenum),右端的数(rinum),从左边开始的最大连续上升子序列的长度(lelis),从右边开始的最大上升子序列的长度(rilis),该区间的最大连续上升子序列的长度(maxlen).具体操作见代码。
代码如下:
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<iterator>
#include<utility>
#include<sstream>
#include<iostream>
#include<cmath>
#include<stack>
using namespace std;
const int INF=1000000007;
const double eps=0.00000001;
const int maxn=100005;
struct node
{
    int le,ri,len;
    int lenum,rinum;
    int maxlis,lelis,rilis;
}tree[4*maxn];
int elem[maxn];
void pushup(int id)
{
    node& fa=tree[id];     //父亲
    node& lson=tree[id*2]; // 左儿子
    node& rson=tree[id*2+1]; //右儿子
    fa.lelis=lson.lelis, fa.rilis=rson.rilis;   //更新
    fa.lenum=lson.lenum, fa.rinum=rson.rinum;
    fa.maxlis=max(lson.maxlis,rson.maxlis);   //左右儿子中的最大值
    if(lson.rinum<rson.lenum)     //如果中间可以形成上升的连续的一段
    {
        if(lson.lelis==lson.len)  fa.lelis+=rson.lelis;   //可扩展
        if(rson.rilis==rson.len)  fa.rilis+=lson.rilis;
        fa.maxlis=max(fa.maxlis,lson.rilis+rson.lelis);   //最大值更新
    }
}
void build_tree(int le,int ri,int id)
{
    node& t=tree[id];
    t.le=le,t.ri=ri,t.len=ri-le+1;
    if(le==ri)
    {
        t.lenum=t.rinum=elem[le];
        t.maxlis=t.lelis=t.rilis=1;
        return;
    }
    int mid=(le+ri)/2;
    build_tree(le,mid,id*2);
    build_tree(mid+1,ri,id*2+1);
    pushup(id);
}
int query(int x,int y,int id)
{
    if(tree[id].le>=x&&tree[id].ri<=y)
    {
        return tree[id].maxlis;
    }
    int mid=(tree[id].le+tree[id].ri)/2;
    int ret=0;
    if(x<=mid)  ret=max(ret,query(x,y,id*2));  //左边
    if(y>mid)   ret=max(ret,query(x,y,id*2+1));// 右边
    if(tree[id*2].rinum<tree[id*2+1].lenum) ret=max(ret,min(mid-x+1,tree[id*2].rilis)+min(y-mid,tree[id*2+1].lelis));//中间
    return ret;
}
void update(int id,int pos,int val)
{
    if(tree[id].le==tree[id].ri)
    { tree[id].lenum=tree[id].rinum=val;  //单点更新
        return;
    }
    int mid=(tree[id].le+tree[id].ri)/2;
    if(pos<=mid)  update(id*2,pos,val);
    else  update(id*2+1,pos,val);
    pushup(id);
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int N,M;
        cin>>N>>M;
        for(int i=1;i<=N;i++)  scanf("%d",&elem[i]);
        build_tree(1,N,1);
        while(M--)
        {
            char S[5];
            int from,to;
            scanf("%s%d%d",S,&from,&to);
            if(S[0]=='Q')  printf("%d\n",query(from+1,to+1,1));
            else  update(1,from+1,to);
        }
    }
    return 0;
}
View Code

 

 
posted @ 2015-08-24 20:42  wust_ouyangli  阅读(186)  评论(0编辑  收藏  举报