hdu 3308 (线段树)

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

题目大意:求区间最长连续递增

解题思路:维护左边起最长,右边为终点最长,当前区间最长得满足要求得序列即可。

#include<iostream>
#include<cstdio>
#include<stack>
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define inf 0x3f3f3f3f
#define LL long long
#define fir first
#define sec second
#define lson rt<<1
#define rson rt<<1|1
#define sq(x) (x)*(x)
#define sca(x) scanf("%d",&x)
#define pb(x) push_back(x)
using namespace std;
#define N 100005
#define maxn 2000005

int a[N];
struct node
{
    int pre,shr,mid;
    int ln,rn;
}T[N<<2];

node push_up(node lrt,node rrt,int llen,int rlen)
{
    node rt;
    rt.ln=lrt.ln,rt.rn=rrt.rn;
    if(lrt.pre==llen&&lrt.rn<rrt.ln)rt.pre=lrt.pre+rrt.pre;
    else rt.pre=lrt.pre;
    if(rrt.shr==rlen&&rrt.ln>lrt.rn)rt.shr=rrt.shr+lrt.shr;
    else rt.shr=rrt.shr;
    rt.mid=max(lrt.mid,rrt.mid);
    if(lrt.rn<rrt.ln)
    {
        rt.mid=max(rt.mid,lrt.shr+rrt.pre);
    }
    return rt;
}

void build(int l,int r,int rt)
{
    if(l==r)
    {
       T[rt].pre=T[rt].shr=T[rt].mid=1;
       T[rt].ln=T[rt].rn=a[l];
       return ;
    }
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    T[rt]=push_up(T[rt<<1],T[rt<<1|1],(r-l+1)-(r-l+1)/2,(r-l+1)/2);
}

void update(int l,int r,int rt,int id,int val)
{
    if(l==r)
    {
       T[rt].ln=T[rt].rn=val;
       return ;
    }
    int m=(l+r)>>1;
    if(id<=m) update(l,m,rt<<1,id,val);
    else update(m+1,r,rt<<1|1,id,val);
    T[rt]=push_up(T[rt<<1],T[rt<<1|1],(r-l+1)-(r-l+1)/2,(r-l+1)/2);
}

node query(int ql,int qr,int l,int r,int rt)
{
    if(l>=ql && r<=qr)
    {
        return T[rt];
    }
    int m=(l+r)>>1;
    if(qr<=m) return query(ql,qr,l,m,rt<<1);
    else if(ql>m) return query(ql,qr,m+1,r,rt<<1|1);
    else
    {
        node tmp1=query(ql,m,l,m,rt<<1);
        node tmp2=query(m+1,qr,m+1,r,rt<<1|1);
        node tmp=push_up(tmp1,tmp2,m-ql+1,qr-m);
        return tmp;
    }
}

int n,m;
void solve()
{
    char s[4];
    int x,y;
    scanf("%s%d%d",s,&x,&y);
    if(s[0]=='Q')
    {
        x++,y++;
        printf("%d\n",query(x,y,1,n,1).mid);
    }
    else
    {
        x++;
        update(1,n,1,x,y);
    }
}
int main()
{
    int cas;
    sca(cas);
    while(cas--)
    {
        scanf("%d%d",&n,&m);
        rep(i,1,n)sca(a[i]);
        build(1,n,1);
        rep(i,1,m)solve();
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值