- #include <iostream>
- #include<algorithm>
- #include<cstdio>
- using namespace std;
- #define M 100005
- int tree[40][M];
- int toLeft[40][M];
- int sorted[M];
- int n,m;
- void build(int level,int ll,int rr){
- if(ll==rr)return;
- int mid=(ll+rr)>>1;
- int i,suppose;
- suppose=mid-ll+1;
- for(i=ll;i<=rr;i++){
- if(tree[level][i]<sorted[mid]){
- suppose--;
- }
- }
- int lpos=ll,rpos=mid+1;
- for(i=ll;i<=rr;i++){
- if(i==ll){
- toLeft[level][i]=0;
- }else{
- toLeft[level][i]=toLeft[level][i-1];
- }
- if(tree[level][i]<sorted[mid]){
- toLeft[level][i]++;
- tree[level+1][lpos++]=tree[level][i];
- }else if(tree[level][i]>sorted[mid]){
- tree[level+1][rpos++]=tree[level][i];
- }else{
- if(suppose!=0){
- suppose--;
- toLeft[level][i]++;
- tree[level+1][lpos++]=tree[level][i];
- }else{
- tree[level+1][rpos++]=tree[level][i];
- }
- }
- }
- build(level+1,ll,mid);
- build(level+1,mid+1,rr);
- }
- //在[left,right]数据中查询[qleft,qright]中第k大的数据
- int query(int level,int left,int right,int qleft,int qright,int k){
- if( qleft==qright)
- return tree[level][qleft];
- int s;//代表[left,qleft)之间有多个个元素被分到左边
- int ss;//[qleft, qright]内将被划分到左子树的元素数目
- int mid=(left+right)>>1;
- if(left==qleft){
- s=0;
- ss=toLeft[level][qright];
- }else{
- s=toLeft[level][qleft-1];
- ss=toLeft[level][qright]-s;
- }
- int newl,newr;
- if(k<=ss){//查询左边
- newl=left+s;
- newr=left+s+ss-1;
- return query(level+1,left,mid,newl,newr,k);
- }else{//查询右边
- newl=mid-left+1+qleft-s;
- newr=mid-left+1+qright-s-ss;
- return query(level+1,mid+1,right,newl, newr,k - ss);
- }
- }
- int solve(int ll,int rr,int h){
- int l=1,r=(rr-ll)+1;
- int mid;
- int ans=0;
- while(l<=r){
- mid=(l+r)>>1;
- int tmp=query(0,1,n,ll,rr,mid);
- if(tmp<=h){
- ans=mid;
- l=mid+1;
- }else{
- r=mid-1;
- }
- }
- return ans;
- }
- int main(){
- int t,ti=1;
- int i;
- scanf("%d",&t);
- while(t--){
- scanf("%d %d",&n,&m);
- for(i=1;i<=n;i++){
- scanf("%d",&tree[0][i]);
- sorted[i]=tree[0][i];
- }
- sort(sorted+1,sorted+n+1);
- build(0,1,n);
- printf("Case %d:\n",ti++);
- int ll,rr,h;
- for(i=0;i<m;i++){
- scanf("%d %d %d",&ll,&rr,&h);
- ll++,rr++;
- if(ll==rr){
- if(tree[0][ll]<=h){
- printf("1\n");
- }else{
- printf("0\n");
- }
- }else{
- printf("%d\n",solve(ll,rr,h));
- }
- }
- }
- return 0;
- }
本文出自 “每天进步一点点” 博客,请务必保留此出处http://sbp810050504.blog.51cto.com/2799422/1016363