洛谷P1533 可怜的狗狗 题解 主席树/可持久化线段树 求区间第k小模板题

题目链接:https://www.luogu.com.cn/problem/P1533

解题思路:

主席树求区间第k小模板题

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e7 + 5;
const int inf = INT_MAX;

int n, m, a, tr[maxn], ls[maxn], rs[maxn], rt[maxn], idx;

void push_up(int u) {
    tr[u] = tr[ ls[u] ] + tr[ rs[u] ];
}

void ins(int p, int l, int r, int pu, int &u) {
    if (!u)
        u = ++idx;
    if (l == r) {
        tr[u] = 1;
        return;
    }
    int mid = l + (r - l) / 2;
    if (p <= mid) {
        rs[u] = rs[pu];
        ins(p, l, mid, ls[pu], ls[u]);
    }
    else {
        ls[u] = ls[pu];
        ins(p, mid+1, r, rs[pu], rs[u]);
    }
    push_up(u);
}

int query(int k, int l, int r, int pu, int u) {
    if (l == r) {
        return l;
    }
    int cnt = tr[ ls[u] ] - tr[ ls[pu] ], mid = l + (r - l) / 2;
    if (cnt >= k)
        return query(k, l, mid, ls[pu], ls[u]);
    else
        return query(k-cnt, mid+1, r, rs[pu], rs[u]);
}

void test(int l, int r, int u) {
    if (!u) return;
    if (l == r) return;
    int mid = (l + r) / 2;
    test(l, mid, ls[u]);
    test(mid+1, r, rs[u]);
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a);
        ins(a, 0, inf, rt[i-1], rt[i]);
    }
    while (m--) {
        int l, r, k;
        scanf("%d%d%d", &l, &r, &k);
        printf("%d\n", query(k, 0, inf, rt[l-1], rt[r]));
    }
    return 0;
}
posted @ 2025-04-17 18:14  quanjun  阅读(10)  评论(0)    收藏  举报