序列内第k小查询(线段树)

最近请教了一下大佬怎么求序列内第k大查询,自己又捣鼓了一下,虽然还没有懂得区间第k大查询,不过姑且做一个记录先吧

因为每个元素大小可能很大而元素之间不连续,所以我们先离散化处理一下,程序中的ori[ ]代表原序列,离散化后每个key对应一个值,mem[ ]存的是key对应的值:mem[i]代表离散化后 i 代表的值,a[i]代表离散化后有几个i对应的值(mem[i]的个数)

离散化之后建树,sum中存的是有序的元素总个数具体可以看程序,那么如何查询?我们查询线段树的sum,若tree[lid].sum >= k ,说明第k大一定在左儿子区间,因为线段树是以有序数列来构建的,每个叶子排起来是有序的(抠一下手指就出来了),说明k在左边。同理 若 tree[lid].sum < k 说明左边全部在一起都没有 k 个,答案自然就在右边了

因为从右边区间出发,已经排除全部左边节点了,所以k要减去左边的sum

这样一直找到叶子节点,找到的叶子对应的就是离散化后的key了,我们在利用mem输出就好

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
int RD(){
    int out = 0,flag = 1;char c = getchar();
    while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
    while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
    return flag * out;
    }
#define lid (id << 1)
#define rid (id << 1) | 1
const int maxn = 100019;
int num,na;
int ori[maxn];
int mem[maxn];
struct sag_tree{
    int l,r,sum;
    }tree[maxn << 2];
int a[maxn];
void build(int id,int l,int r){
    tree[id].l = l;
    tree[id].r = r;
    if(l == r){
        tree[id].sum = a[l];
        return ;
        }
    int mid = (l + r) >> 1;
    build(lid,l,mid);
    build(rid,mid + 1,r);
    tree[id].sum = tree[lid].sum + tree[rid].sum;
    }
    
int query(int id,int k){
    if(tree[id].l == tree[id].r)return tree[id].l;
    if(tree[lid].sum < k)return query(rid,k - tree[lid].sum);
    else if(tree[lid].sum >= k)return query(lid,k);
    }
    
int main(){
    num = RD();na = RD();
    for(int i = 1;i <= num;i++){
        ori[i] = RD();
        }
    sort(ori + 1,ori + 1 + num);
    int n = 0;
    for(int i = 1;i <= num;i++){
        if(i == 1 || ori[i] != ori[i - 1]){
            n++;
            }
        a[n]++;
        mem[n] = ori[i];
        }
    build(1,1,n);
    int k;
    for(int i = 1;i <= na;i++){
        k = RD();
        cout<<mem[query(1,k)]<<endl;
        }
    return 0;
    }

推一下可以得到,序列第k大就是序列第(num - k + 1)小,所以很好解决


upd 18.7.9

后面发现,其实这也是treap查找序列第k大的方法

猜你喜欢

转载自www.cnblogs.com/Tony-Double-Sky/p/9283241.html