还不懂 先把代码贴在这里
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
#define maxn 100007
struct Node
{
int l,r,sum;
}T[maxn*40];//线段树一般开4倍 主席树一般开40倍s
int a[maxn];//用来存放数据
int rt[maxn];//用来存放根节点的id
int cnt = 0;//代表其数量
int n,m;//n各节点 m 个查询
vector<int> pq;
int getId(int x)//进行离散化 就是通过二分查找来或得其下标
{
return lower_bound(pq.begin(),pq.end(),x) - pq.begin() + 1;
}
void update(int l,int r,int &x,int y,int pos)//x是代表第x的状态的线段树 y代表的是当前状态的线段树的树根 pos 是代表要修改的节点
{
T[++cnt] = T[y];
T[cnt].sum++;
x = cnt;
if(l==r)
return;
int mid = (l+r)/2;
if(pos <= mid )//想左子树进行更新
update(l,mid,T[x].l,T[y].l,pos);
else
update(mid +1 ,r,T[x].r,T[y].r,pos);
}
int query(int l,int r,int x,int y,int k)//k表示区间第k大
{
if(l==r)
return l;
int sum = T[T[y].l].sum - T[T[x].l].sum;
int mid = (l + r)/2;
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%d",&n,&m);
for(int i = 1;i<=n; i++)
scanf("%d",&a[i]),pq.push_back(a[i]);
//对元素进行排序 为了用二分
sort(pq.begin(),pq.end());
pq.reserve(pq.size());
//把元素擦掉
pq.erase(unique(pq.begin(),pq.end()),pq.end());
for(int i =1;i<=n;i++)
{
update(1,n,rt[i],rt[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",pq[query(1,n,rt[x-1],rt[y],k) -1]);
}
return 0;
}