主席树板子修改下数组大小后复制过来RE了后俩点,看不出哪爆了……
#include<bits/stdc++.h>;
using namespace std;
int n,q,a[300005],c[300005],root[3000005],rel[300005],cnt=0,p=0,x,y,d;
struct ever_tree{
int lson,rson,ll,rr,counter;
}t[6000005];
int build(int l,int r){//再离散化后的数值上建初始主席树,起初所有节点权值为零
++p;//节点编号
t[p].ll=l,t[p].rr=r,t[p].counter=0;//区间初始化
if(l==r){
t[p].lson=t[p].rson=0;
return p;
}
int mid=l+r>>1,k=p;//注意用k保存节点编号p
t[k].lson=build(l,mid),t[k].rson=build(mid+1,r);//记录左右儿子的编号
return k;
}
void mend(int l,int k){//自下向上跟新并新建节点
if(t[k].ll==l&&t[k].rr==l){
t[++p].ll=t[k].ll;t[p].rr=t[k].rr;t[p].counter=t[k].counter+1;
t[p].lson=t[p].rson=0;
return;
}
++p;
int mid=t[k].ll+t[k].rr>>1,h=p;//用h记录当前节点编号
if(l<=mid){//判断修改点在哪个儿子
mend(l,t[k].lson);
t[h].lson=h+1;t[h].rson=t[k].rson;
}
else{
mend(l,t[k].rson);
t[h].rson=h+1;t[h].lson=t[k].lson;
}
t[h].ll=t[k].ll,t[h].rr=t[k].rr;//记得传递区间范围
t[h].counter=t[t[h].lson].counter+t[t[h].rson].counter;//跟新权值
}
int ask(int k,int g,int w){//询问
if(t[k].ll==t[k].rr)return t[k].ll;//找到答案
int u=t[t[g].lson].counter-t[t[k].lson].counter;//r版本与l-1版本的主席树权值相减,即为a[l]~a[r]数的分布情况
if(u>=w)return ask(t[k].lson,t[g].lson,w);//因为左子树代表的数的范围一定比右子树小
else return ask(t[k].rson,t[g].rson,w-u);//所有可以根据左右儿子数的数量,判断答案在哪棵子树
}
int main(){
scanf("%d%d",&n,&q);
for(int i(1);i<=n;++i)scanf("%d",&a[i]);
memcpy(c,a,sizeof(a));
sort(c+1,c+n+1);
c[0]=c[1]-1;
for(int i(1);i<=n;++i){
if(c[i]!=c[i-1])rel[++cnt]=c[i];
}
for(int i(1);i<=n;++i){
a[i]=lower_bound(rel+1,rel+cnt+1,a[i])-rel;
}//离散化
build(1,cnt);
root[0]=1;//第i个个版本的主席树表示区间1~i的数组上,各数值出现的个数
//如离散化后数组为3,2,2,5,4,1,6,2,1
//则第5个版本的主席树上代表2~3区间的节点权值为3,即a[1]~a[5]中有3个数在2~3之间
for(int i(1);i<=n;++i){
root[i]=p+1;//依次记录各个版本主席树的根节点
mend(a[i],root[i-1]);//把数值a[i]加1
}
while(q--){
scanf("%d%d%d",&x,&y,&d);
printf("%d\n",rel[ask(root[x-1],root[y],d)]);//直接查询
}
return 0;
}