题意:给你n个数,m次操作,每次操作询问区间[l, r] 中第K大的数。(n、m <= 1e5)
思路:主席树模板题 (主席树知识:点击打开链接)
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e5+5;
int a[maxn], Hash[maxn];
int lson[maxn<<5], rson[maxn<<5], sum[maxn<<5];
int T[maxn];
int m, n, tot;
int build(int l, int r)
{
int rt = ++tot;
sum[rt] = 0;
if(l < r)
{
int mid = (l+r)/2;
lson[rt] = build(l, mid);
rson[rt] = build(mid+1, r);
}
return rt;
}
int update(int pre, int l, int r, int x)
{
int rt = ++tot;
lson[rt] = lson[pre], rson[rt] = rson[pre], sum[rt] = sum[pre]+1;
if(l < r)
{
int mid = (l+r)/2;
if(x <= mid)
lson[rt] = update(lson[pre], l, mid, x);
else
rson[rt] = update(rson[pre], mid+1, r, x);
}
return rt;
}
int query(int u, int v, int l, int r, int k)
{
if(l >= r) return l;
int mid = (l+r)/2;
int num = sum[lson[v]]-sum[lson[u]];
if(num >= k)
return query(lson[u], lson[v], l, mid, k);
else
return query(rson[u], rson[v], mid+1, r, k-num);
}
int main(void)
{
while(cin >> n >> m)
{
tot = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
Hash[i] = a[i];
}
sort(Hash+1, Hash+1+n);
int d = unique(Hash+1, Hash+1+n)-Hash-1;
T[0] = build(1, d);
for(int i = 1; i <= n; i++)
{
int x = lower_bound(Hash+1, Hash+1+d, a[i])-Hash;
T[i] = update(T[i-1], 1, d, x);
}
while(m--)
{
int l, r, k;
scanf("%d%d%d", &l, &r, &k);
int ans = query(T[l-1], T[r], 1, d, k);
printf("%d\n", Hash[ans]);
}
}
return 0;
}