主席树做法,第一次写,1A了。
主要思路为,数据排序去重后,从原始数据第一个添加到最后一个构建n棵树,树上内容为根据排序去重结果的数的出现次数,给定l r 区间,第x个数,用第r减去第l-1的树上,找到需要找的第x个数,输出即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <string>
#include <vector>
//#include <iostream>
using namespace std;
int head[101000],total=0;
struct node{int lson,rson,sum;} tree[3001000];
int inf[101000],num[101000];
int build(int l,int r,int now)
{
if(l==r)
return 0;
total++;
tree[now].lson=total;
total++;
tree[now].rson=total;
build( l, (l+r)/2, tree[now].lson);
build( (l+r)/2+1, r, tree[now].rson);
return 0;
}
int update(int number,int l,int r,int now,int pre)
{
if(l==r)
{
tree[now].sum++;
return 0;
}
int mid=(l+r)/2;
if(number<=num[mid])
{
total++;
tree[now].lson=total;
tree[now].rson=tree[pre].rson;
update(number,l,(l+r)/2,tree[now].lson,tree[pre].lson);
}
else
{
total++;
tree[now].rson=total;
tree[now].lson=tree[pre].lson;
update(number,(l+r)/2+1,r,tree[now].rson,tree[pre].rson);
}
tree[now].sum=tree[tree[now].lson].sum+tree[tree[now].rson].sum;
return 0;
}
int ques(int pre,int now,int number,int l,int r,int temp)
{
if(l==r)
return num[l];
int mid=(l+r)/2;
if(tree[tree[now].lson].sum-tree[tree[pre].lson].sum+temp>=number)
return ques(tree[pre].lson,tree[now].lson,number,l,mid,temp);
else
return ques(tree[pre].rson,tree[now].rson,number, mid+1,r,temp+tree[tree[now].lson].sum-tree[tree[pre].lson].sum);
}
int main()
{
int i,j,n,k,m,l,p;
scanf("%d%d",&m,&n);
for(i=1;i<=m;i++)
{
scanf("%d",&inf[i]);
num[i]=inf[i];
}
sort(num+1,num+1+m);
int xx=unique(num+1,num+1+m)-num+1;
xx--;
head[0]=total;
build(1,xx,head[0]);
for(i=1;i<=m;i++)
{
total++;
head[i]=total;
update(inf[i],1,xx,head[i],head[i-1]);
}
while(n--)
{
scanf("%d%d%d",&j,&k,&l);
printf("%d\n",ques(head[j-1],head[k],l,1,xx,0));
}
return 0;
}