HDU 3308 LCIS

LCIS

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3553    Accepted Submission(s): 1577

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<=105).
The next line has n integers(0<=val<=105).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=105)
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
 
求最长最长公共上升子序列
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn  100005
using namespace std;

int mov[maxn<<2],las[maxn<<2],ras[maxn<<2];
int va[maxn];

void pushup(int rt,int l,int r)
{
    las[rt]=las[rt<<1];
    ras[rt]=ras[rt<<1|1];
    mov[rt]=max(mov[rt<<1],mov[rt<<1|1]);
    int mid=(l+r)>>1;
    int m=(r-l)+1;
    if(va[mid]<va[mid+1]) //左区间的右值小于右区间的左值可以合并
    {
        if(las[rt]==m-(m>>1)) las[rt]+=las[rt<<1|1];
        if(ras[rt]==(m>>1)) ras[rt]+=ras[rt<<1];
        mov[rt]=max(mov[rt],las[rt<<1|1]+ras[rt<<1]);
    }
}
void build(int l,int r,int rt)
{
    if(l==r)
    {
        mov[rt]=las[rt]=ras[rt]=1;
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt,l,r);
}
void  update(int a,int l,int r,int rt)
{
    if(l==r)
    {
        return;
    }
    int m=(l+r)>>1;
    if(a<=m) update(a,lson);
    else update(a,rson);
    pushup(rt,l,r);
}

int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        return mov[rt];
    }
    int m=(l+r)>>1;
    if(R<=m) return query(L,R,lson); //与一般不同,不能是子集,只能全部属于才能直接查询子区间 返回子区间的mlen
    if(L>m) return query(L,R,rson);  //否则是确认儿子区间是否能合并,并在三者之间取最大值

    int ta,tb;
    ta=query(L,R,lson);
    tb=query(L,R,rson);
    int ans;
    ans=max(ta,tb);
    if(va[m]<va[m+1])  //同上
    {
        int temp;
        temp=min(ras[rt<<1],m-L+1)+min(las[rt<<1|1],R-m);
        ans=max(temp,ans);
    }
    return ans;
}

int main()
{
    int T,n,m;
    int i,j;
    char f[2];
    int a,b;
    scanf("%d",&T);
    for(i=0;i<T;i++)
    {
        scanf("%d %d",&n,&m);
        for(j=1;j<=n;j++)
           scanf("%d",&va[j]);
        build(1,n,1);
        while(m--)
        {
            scanf("%s",&f);
            if(f[0]=='U')
            {
                scanf("%d %d",&a,&b);
                a++;
                va[a]=b;
                update(a,1,n,1);
            }
            else
            {
                scanf("%d %d",&a,&b);
                a++,b++;
                printf("%d\n",query(a,b,1,n,1));
            }
        }
    }
    return 0;
}
View Code

 

posted @ 2014-03-23 08:57  霖‘  阅读(157)  评论(0编辑  收藏  举报