链接:点击打开链接
题意:求区间第k大
代码:
#include <map>
#include <set>
#include <queue>
#include <string>
#include <math.h>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
const int siz=100005;
int id,a[siz],rk[siz];
map<int,int> mp1,mp2;
map<int,int>::iterator ite;
struct node{
int l,r,sum;
}tr[siz*30];
void build(int l,int r,int &rt){
int mid;
rt=++id;
if(l==r)
return;
mid=(l+r)>>1;
build(l,mid,tr[rt].l);
build(mid+1,r,tr[rt].r);
}
void change(int p,int pre,int l,int r,int &rt){
int mid;
rt=++id;
tr[rt]=tr[pre];
tr[rt].sum++;
if(l==r)
return;
mid=(l+r)>>1;
if(p<=mid)
change(p,tr[pre].l,l,mid,tr[rt].l);
else
change(p,tr[pre].r,mid+1,r,tr[rt].r);
}
int query(int pre,int l,int r,int rt,int k){
int sum,mid;
if(l==r)
return l;
mid=(l+r)>>1;
sum=tr[tr[rt].l].sum-tr[tr[pre].l].sum;
if(k<=sum)
return query(tr[pre].l,l,mid,tr[rt].l,k);
else
return query(tr[pre].r,mid+1,r,tr[rt].r,k-sum);
}
int main(){ //主席树模板题
int i,j,t,n,m,u,v,k,op;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
mp1.clear();
mp2.clear();
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
mp1[a[i]]=1;
}
id=op=0;
for(ite=mp1.begin();ite!=mp1.end();ite++){
ite->second=++op;
mp2[op]=ite->first;
}
build(1,op,rk[0]);
for(i=1;i<=n;i++)
change(mp1[a[i]],rk[i-1],1,op,rk[i]);
for(i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&k);
printf("%d\n",mp2[query(rk[u-1],1,op,rk[v],k)]);
}
}
return 0;
}