M个询问询问区间K小值。
我们用K大数查询这道题的思路整体二分。
这道题直接套用K大数查询需要带两个log。
我们把询问l~r拆为两个询问1~r和1~l-1,那么每个询问都变成一个前缀,于是我们想着搞一波线性作法。
观察到对于答案区间为l~r,我们只需要扫描在这个区间内的数。
也就是说对于l~r中的数,<=mid的数继续归到左区间其余归到右区间。
一个区间内的询问按照右端点排序,然后就可以线性做。
总复杂度n log n。
注意本题答案范围比较大故先进行离散化。
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=100000+10;
struct dong{
int a,cnt,x;
bool p;
};
dong ask[maxn*2];
int h1[maxn*5],h2[maxn*5],h3[maxn*5],la1[maxn*5],la2[maxn*5],la3[maxn*5],n1[maxn*20],n2[maxn*20],n3[maxn*20],g1[maxn*20],g2[maxn*20],g3[maxn*20];
int a[maxn],h[maxn],ans[maxn],rank[maxn],id[maxn*2];
int i,j,k,l,t,n,m,t1,t2,t3;
//h1=dl h2=ld h3=que
void add1(int x,int y){
g1[++t1]=y;
n1[la1[x]]=t1;
la1[x]=t1;
if (!h1[x]) h1[x]=t1;
}
void add2(int x,int y){
g2[++t2]=y;
n2[la2[x]]=t2;
la2[x]=t2;
if (!h2[x]) h2[x]=t2;
}
void add3(int x,int y){
g3[++t3]=y;
n3[la3[x]]=t3;
la3[x]=t3;
if (!h3[x]) h3[x]=t3;
}
void solve(int p,int l,int r){
int j,i,k,t,num=0;
if (l==r){
t=h3[p];
while (t){
j=g3[t];
ans[j]=h[l];
t=n3[t];
}
return;
}
int mid=(l+r+1)/2;
i=h2[p];k=h1[p];
while (i){
t=g2[i];
while (k){
j=g1[k];
if (ask[j].a>=t) break;
ask[j].x=num;
k=n1[k];
}
if (a[t]<=mid-1) num++;
i=n2[i];
}
while (k){
j=g1[k];
ask[j].x=num;
k=n1[k];
}
i=h3[p];
while (i){
t=g3[i];
if (ask[t*2].cnt+ask[t*2].x-ask[t*2-1].cnt-ask[t*2-1].x<=rank[t]-1){
ask[t*2].cnt+=ask[t*2].x;
ask[t*2-1].cnt+=ask[t*2-1].x;
ask[t*2].x=ask[t*2-1].x=0;
ask[t*2-1].p=ask[t*2].p=1;
add3(p*2+1,t);
}
else{
ask[t*2].x=ask[t*2-1].x=0;
ask[t*2-1].p=ask[t*2].p=0;
add3(p*2,t);
}
i=n3[i];
}
i=h1[p];
while (i){
t=g1[i];
if (ask[t].p) add1(p*2+1,t);else add1(p*2,t);
i=n1[i];
}
i=h2[p];
while (i){
t=g2[i];
if (a[t]<=mid-1) add2(p*2,t);else add2(p*2+1,t);
i=n2[i];
}
solve(p*2,l,mid-1);
solve(p*2+1,mid,r);
}
bool cmp(int a,int b){
return ask[a].a<ask[b].a;
}
int main(){
scanf("%d%d",&n,&m);
fo(i,1,n){
scanf("%d",&a[i]);
h[i]=a[i];
}
sort(h+1,h+n+1);
fo(i,1,n) a[i]=lower_bound(h+1,h+n+1,a[i])-h,add2(1,i);
fo(i,1,m){
scanf("%d%d%d",&j,&k,&l);
rank[i]=l;
add3(1,i);
ask[i*2-1].a=j-1;
ask[i*2].a=k;
}
fo(i,1,m*2) id[i]=i;
sort(id+1,id+m*2+1,cmp);
fo(i,1,m*2) add1(1,id[i]);
solve(1,1,n);
fo(i,1,m) printf("%d\n",ans[i]);
}