1 10 10 0 5 2 7 5 4 3 8 7 7 2 8 6 3 5 0 1 3 1 1 9 4 0 1 0 3 5 5 5 5 1 4 6 3 1 5 7 5 7 3
Case 1: 4 0 0 3 1 2 0 1 5 1
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=100010;
struct node
{
int num[maxn];
int val[maxn];
}tree[30];
int sorted[maxn];
void build(int ind,int l,int r)
{
if(l == r)
return ;
int mid=(l+r)>>1;
int isame=mid-l+1;
for(int i=l;i<=r;i++)
if(sorted[mid] > tree[ind].val[i])
isame--;
int ln=l;
int rn=mid+1;
for(int i = l;i<=r;i++)
{
if(i == l)
tree[ind].num[i]=0;
else
tree[ind].num[i]=tree[ind].num[i-1];
if(tree[ind].val[i] < sorted[mid])
{
tree[ind].num[i]++;
tree[ind+1].val[ln++]=tree[ind].val[i];
}
else if(tree[ind].val[i] > sorted[mid])
tree[ind+1].val[rn++]=tree[ind].val[i];
else
{
if(isame)
{
isame--;
tree[ind].num[i]++;
tree[ind+1].val[ln++]=tree[ind].val[i];
}
else
tree[ind+1].val[rn++]=tree[ind].val[i];
}
}
build(ind+1,l,mid);
build(ind+1,mid+1,r);
}
int query(int ind,int l,int r,int a,int b,int k)
{
if(a == b)
return tree[ind].val[a];
int s0,s1;
int mid=(l+r)>>1;
if(a == l)
{
s0=0;
s1=tree[ind].num[b];
}
else
{
s0=tree[ind].num[a-1];
s1=tree[ind].num[b]-s0;
}
if(s1 >= k)
{
a=l+s0;
b=l+s0+s1-1;
return query(ind+1,l,mid,a,b,k);
}
else
{
a=mid-l+1+a-s0;
b=mid-l+1+b-s0-s1;
return query(ind+1,mid+1,r,a,b,k-s1);
}
}
int main()
{
int t;
scanf("%d",&t);
int p=1;
while(t--)
{
int n, m, x, y;
int k;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&sorted[i]);
tree[0].val[i]=sorted[i];
}
sort(sorted+1,sorted+n+1);
build(0,1,n);
printf("Case %d:\n",p++);
while(m--)
{
scanf("%d%d%d",&x,&y,&k);
x++;
y++;
int l=1,r=(y-x+1),mid,ans=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(query(0,1,n,x,y,mid) <= k)//第mid大元素小于k
{
l=mid+1;
ans=mid;
}
else
r=mid-1;
}
printf("%d\n",ans);
}
}
return 0;
}