线段树求解区间第k大

这篇博客探讨了如何使用线段树解决区间第k大数的问题,避免了通过归并排序建树导致的空间浪费。通过直接记录节点对应数组范围的方式简化了线段树的结构,并详细介绍了查询过程,包括查询给定值在给定范围内的下标以及在特定节点中的下标。文章以即将举行的蓝桥杯比赛为背景,鼓励读者掌握这一技巧。
摘要由CSDN通过智能技术生成

具体哪道题目就不说了,区间第k大可以说是很常见的题目。写了一上午线段树终于是记起了一点以前学过的东西。

这里说的是没有修改的区间查询。对于线段树的结构体,一开始搜了一下,说是要按照归并排序的方法去建树,所以说每个节点要记录数组咯??这样的话每个节点还要记一个数组,太麻烦,空间占用也变大了。所以有另一种方法,直接用一个数组,在节点中记录该节点对应的该数组中的范围,这样就可以节省空间。

建好树之后就是查询,这里要到两个查询,第一个是查询给定值在给定范围内的下标,第二个查询是第一个查询中要调用的,用来寻找在具体的某一个节点中它的下标。最后在主程序中二分答案,找到其在给定范围的下标,判断即可。

#include<stdio.h>
#include<string.h>
#define maxn 10100
#define inf 1111111111
struct s{
    int l,r,ll,rr;
};
s tr[maxn*4];
int d[maxn*20],cnt;
int a[maxn];
void build(int rt,int lr,int rr){
    tr[rt].l=lr;
    tr[rt].r=rr;
    if(lr==rr){
        d[++cnt]=a[lr];
        tr[rt].ll=cnt;
        tr[rt].rr=cnt;
     //   printf("%d   \n",d[lr]);
        return ;
    }
    int mid=(tr[rt].l+tr[rt].r)>>1;
    build(rt*2,lr,mid);
    build(rt*2+
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值