HDU 2665 Kth number(主席树静态区间第K大)题解

题意:问你区间第k大是谁

思路:主席树就是可持久化线段树,他是由多个历史版本的权值线段树(不是普通线段树)组成的。

具体可以看q学姐的B站视频

代码:

#include<cmath>
#include<set>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e5 + 10;
const int M = maxn * 30;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
int n, q, tot;
int a[maxn], root[maxn];
vector<int> st;
int getId(int x){
    return lower_bound(st.begin(), st.end(),x) - st.begin() + 1;
}
struct node{
    int lson, rson;
    int sum;
}T[maxn * 40];
void update(int l, int r, int &now, int pre, int v, int pos){
    T[++tot] = T[pre], T[tot].sum += v, now = tot;
    if(l == r) return;
    int m = (l + r) >> 1;
    if(m >= pos)
        update(l, m, T[now].lson, T[pre].lson, v, pos);
    else
        update(m + 1, r, T[now].rson, T[pre].rson, v, pos);
}
int query(int l, int r, int pre, int now, int k){
    if(l == r) return l;
    int m = (l + r) >> 1;
    int sum = T[T[now].lson].sum - T[T[pre].lson].sum;
    if(sum >= k)
        return query(l, m, T[pre].lson, T[now].lson, k);
    else
        return query(m + 1, r, T[pre].rson, T[now].rson, k - sum);
}
int main(){
    int t;
    scanf("%d", &t);
    while(t--){
        tot = 0;
        scanf("%d%d", &n, &q);
        st.clear();
        for(int i = 1; i <= n; i++)
            scanf("%d", &a[i]), st.push_back(a[i]);
        sort(st.begin(), st.end());
        st.erase(unique(st.begin(), st.end()), st.end());

        for(int i = 1; i <= n; i++)
            update(1, n, root[i], root[i - 1], 1, getId(a[i]));
        while(q--){
            int l, r, k;
            scanf("%d%d%d", &l, &r, &k);
            printf("%d
", st[query(1, n, root[l - 1], root[r], k) - 1]);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/KirinSB/p/10745320.html