习题:线段树找区间连续最长递增子序列长度

该文讨论如何在序列中找到某一区间的最长连续递增子序列长度,支持查询和单点修改操作。采用节点结构体存储区间信息,通过二叉树结构实现数据更新和查询,关键在于push_up和query函数的实现,以及在更新和查询过程中对边界情况的处理。
摘要由CSDN通过智能技术生成

题意:寻找一段序列某一区间的连续最长递增子序列长度,有查询和单点修改的操作

编号从0开始,多组样例

思路点拨:节点结构体存储实际信息:mv:区间最长,lv:左端最长 rv:右端最长

关键代码:

struct Tree{
    int lv,rv,mv;
    int l,r;
}tree[MAXN<<2]; 
//结构体构建

//build函数与往常一样

void push_up(int u)
{
    tree[u].lv=tree[u<<1].lv;
    tree[u].rv=tree[u<<1|1].rv;
    tree[u].mv=max(tree[u<<1].mv,tree[u<<1|1].mv);
    
    int mid=(tree[u].l+tree[u].r)>>1;
    int len=tree[u].r-tree[u].l+1;
    if(a[mid]<a[mid+1])
    {
        if(tree[u].lv==len-(len>>1)) tree[u].lv+=tree[u<<1|1].lv;
        if(tree[u].rv==len>>1) tree[u].rv+=tree[u<<1].rv;
        tree[u].mv=max(tree[u].mv,tree[u<<1].rv+tree[u<<1|1].lv);
    }
}
//push_up函数,求出mv,lv,rv   当左右段可能连起来时特殊处理

void update(int x,int y,int k)
{
    if(tree[k].l==tree[k].r)
    {
        a[x]=y;
        return; 
    }
    int mid=(tree[k].l+tree[k].r)>>1;
    if(x<=mid) update(x,y,k<<1);
    else update(x,y,k<<1|1);
    push_up(k);
}
//update函数,注意更改的是数组a

int  query(int l,int r,int k)
{
    if(l<=tree[k].l&&r>=tree[k].r)
    {
        return tree[k].mv;
    }
    int mid=(tree[k].l+tree[k].r)>>1;
    int ans=0;
    if(l<=mid) ans=max(ans,query(l,r,k<<1));
    if(r>mid)  ans=max(ans,query(l,r,k<<1|1));
    if(a[mid]<a[mid+1]) ans=max(ans,min(mid-l+1,tree[k<<1].rv)+min(r-mid,tree[k<<1|1].lv));
    return ans;    
}
//query函数,终点直接返回mv,用临时变量ans保存最大值,注意跨子段时的处理方式

//main函数,注意输入的序号是从零开始的,而编号是从1开始的,处理前要加1.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值