Kth number -hdu2665

归并树,划分树,主席树都能做。

https://www.bilibili.com/video/av4619406/?p=2 资源,对主席树的理解还差了一点,不是很明白它是怎么更新每个节点左儿子和右儿子编号的。

#pragma warning(disable:4996)
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long 
#define mem(arr,in) memset(arr,in,sizeof(arr))
using namespace std;

const int maxn = 1e5 + 5;

int n, m, cnt, kase;
int root[maxn], a[maxn];

struct node { int l, r, sum; } T[maxn * 20];

vector<int> v;
int getid(int x) { return lower_bound(v.begin(), v.end(), x) - v.begin() + 1; }
    
void Update(int l, int r, int &rt, int pre, int pos) {
    T[++cnt] = T[pre], T[cnt].sum++, rt = cnt;
    if (l == r) return;
    int mid = (l + r) >> 1;
    if (mid >= pos) Update(l, mid, T[rt].l, T[pre].l, pos);
    else Update(mid + 1, r, T[rt].r, T[pre].r, pos);
}

int Query(int l, int r, int x, int y, int k) {
    if (l == r) return l;
    int mid = (l + r) >> 1;
    int sum = T[T[y].l].sum - T[T[x].l].sum;
    if (sum >= k) return Query(l, mid, T[x].l, T[y].l, k);
    else return Query(mid + 1, r, T[x].r, T[y].r, k - sum);
}

int main()
{    
    scanf("%d", &kase);
    while (kase--) {
        v.clear(); cnt = 0;

        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++) Update(1, n, root[i], root[i - 1], getid(a[i]));
        for (int i = 1; i <= m; i++) {
            int x, y, k;
            scanf("%d%d%d", &x, &y, &k);
            printf("%d\n", v[Query(1, n, root[x - 1], root[y], k) - 1]);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zgglj-com/p/9052260.html
今日推荐