【线段树】HDU 3308 LCIS

= =

两种操作:

U A B:将A位置更新为B

Q A B:求A-B区间内的最长连续上升子序列的长度

需要四个数组

用num 表示序列

用sum 表示该储存该子树的最长连续上升子序列的长度

用lsum 表示该储存该子树的从子树的第一个num开始的最长连续上升子序列的长度

rsum则表示从结束于该子树最后一个num的最长连续上升子序列的长度

更新操作只需要单点更新即可

在pushup时

rt节点的lsum继承了左子节点的lsum

rt节点的rsum继承了右子节点的rsum

rt的sum则需要取左右子节点的sum最大值以及比较两子节点下的num可能连续形成新的上升序列;

同样查询操作时同样是取左右子节点的最大值和可能形成新的子序列;

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <set>
#include <map>
#define IN     freopen ("in.txt" , "r" , stdin);
#define OUT  freopen ("out.txt" , "w" , stdout);
typedef long long  LL;
const int MAXN = 100110;//点数的最大值
const int MAXM = 20006;//边数的最大值
const int INF = 11521204;
const int mod=1000000007;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int num[MAXN];
int sum[MAXN<<2],lsum[MAXN<<2],rsum[MAXN<<2];
int col[MAXN<<2];
void pushup(int rt,int m,int l)
{
    int lx=m-(m>>1);
    int rx=(m>>1);
    lsum[rt]=lsum[rt<<1];
    rsum[rt]=rsum[rt<<1|1];
    if(lsum[rt]==lx&&num[lx+l-1]<num[lx+l])  lsum[rt]+=lsum[rt<<1|1];
    if(rsum[rt]==rx&&num[lx+l-1]<num[lx+l])  rsum[rt]+=rsum[rt<<1];
    sum[rt]=max(max(sum[rt<<1],sum[rt<<1|1]),num[lx+l-1]<num[lx+l]?rsum[rt<<1]+lsum[rt<<1|1]:0);
}
void build(int l,int r,int rt)
{
    col[rt]=0;
    if(l==r)
    {
        scanf("%d",&num[l]);
        sum[rt]=lsum[rt]=rsum[rt]=1;
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt,r-l+1,l);
}
void update(int x,int cc,int l,int r,int rt)
{
    if(l==r)
    {
        num[l]=cc;
        return ;
    }
    int m=(l+r)>>1;
    if(x<=m)    update(x,cc,lson);
    else   update(x,cc,rson);
    pushup(rt,r-l+1,l);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        return sum[rt];
    }
    int m=(l+r)>>1,res=0;
    if(L<=m)    res=max(res, query(L,R,lson));
    if(m<R)    res=max(res,query(L,R,rson));
    if (num[m] < num[m+1])
        res = max(res, min(m-L+1, rsum[rt<<1])+min(R-m, lsum[rt<<1|1]));
    return res;
}
int main()
{
    int n,m,t;
    IN;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        build(1,n,1);
        while(m--)
        {
            char c[2];
            int a,b;
            scanf("%s%d%d",c,&a,&b);
            if(c[0]=='U')
                update(a+1,b,1,n,1);
            else
                printf("%d\n",query(a+1,b+1,1,n,1));
        }
    }
    return 0;
}

posted @ 2014-08-18 18:45  kewowlo  阅读(121)  评论(0编辑  收藏  举报