主席树模板!!区间第k小(大)代码主要参考b站up主 AgOH

区间第k大查询

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 1000 + 10;
struct Node
{
    int l, r, sum;
} hjt[maxn * 40];
int n, m, a[maxn];
int cnt, root[maxn];
vector<int> v;
bool cmp(int a, int b)
{
    return a > b;
}
int GetID(int x)
{
    return lower_bound(v.begin(), v.end(), x, greater<int>()) - v.begin() + 1;
}
void insert(int L, int R, int pre, int &node, int p) // pre 为上一颗线段树的根节点 ,node为当前线段树的根节点
{
    hjt[++cnt] = hjt[pre];
    node = cnt;
    hjt[node].sum++;
    if (L == R)
        return;
    int mid = (L + R) >> 1;
    if (p <= mid)
        insert(L, mid, hjt[pre].l, hjt[node].l, p);
    else
        insert(mid + 1, R, hjt[pre].r, hjt[node].r, p);
}
int query(int start, int end, int L, int R, int k)
{
    if (start == end)
        return end;
    int mid = (start + end) >> 1;
    int temp = hjt[hjt[R].l].sum - hjt[hjt[L].l].sum;
    if (k <= temp)
        return query(start, mid, hjt[L].l, hjt[R].l, k);
    else
        return query(mid + 1, end, hjt[L].r, hjt[R].r, k - temp);
}
int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("in.txt", "r", stdin);
#endif
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        v.push_back(a[i]);
    }
    sort(v.begin(), v.end(), cmp);
    v.erase(unique(v.begin(), v.end()), v.end());
    // cout << "去重后数组元素" << endl;
    // for (int i = 0; i < v.size(); i++)
    // {
    //     cout << v[i] << " ";
    // }
    // cout << endl;
    for (int i = 1; i <= n; i++)
    {
        // cout << a[i] << " 在去重数组中为第 " << GetID(a[i]) << " 大" << endl;
        insert(1, n, root[i - 1], root[i], GetID(a[i]));
    }
    cin >> m;
    int x, y, k;
    while (m--)
    {
        cin >> x >> y >> k;
        cout << v[query(1, n, root[x - 1], root[y], k) - 1] << endl;
    }
    return 0;
}

区间第k小查询 

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 2e5 + 10;
vector<int> v;
int n, m, a[maxn];   // a为原数组
int cnt, root[maxn]; // root 根节点数组
struct Node
{
    int l, r, sum;
} hjt[maxn * 40];
int GetId(int x)
{
    return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
}
void insert(int L, int R, int pre, int &node, int p) // pre 为上一颗线段树的根节点 ,node为当前线段树的根节点
{
    hjt[++cnt] = hjt[pre];
    node = cnt;
    hjt[node].sum++;
    if (L == R)
        return;
    int mid = (L + R) >> 1;
    if (p <= mid)
        insert(L, mid, hjt[pre].l, hjt[node].l, p);
    else
        insert(mid + 1, R, hjt[pre].r, hjt[node].r, p);
}
int query(int start, int end, int L, int R, int k)
{
    if (start == end)
        return end;
    int mid = (start + end) >> 1;
    int temp = hjt[hjt[R].l].sum - hjt[hjt[L].l].sum;
    if (k <= temp)
        return query(start, mid, hjt[L].l, hjt[R].l, k);
    else
        return query(mid + 1, end, hjt[L].r, hjt[R].r, k - temp);
}
int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("in.txt", "r", stdin);
#endif
    freopen("out.txt", "w", stdout);
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        v.push_back(a[i]);
    }
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    for (int i = 1; i <= n; i++)
    {
        insert(1, n, root[i - 1], root[i], GetId(a[i]));
    }
    int x, y, k;
    while (m--)
    {
        scanf("%d %d %d", &x, &y, &k);
        printf("%d\n", v[query(1, n, root[x - 1], root[y], k)-1]);
    }
    cout << cnt << endl;
    return 0;
}
发布了51 篇原创文章 · 获赞 21 · 访问量 3077

猜你喜欢

转载自blog.csdn.net/qq_44115065/article/details/103729963