第一次写归并排序+线段树 感觉受益颇深
这道题是求在[s,t]区间内的第k大元素
首先使用归并排序可以每次得到任意2^n区间内的有序状态
在此基础上使用线段树分离区间
最后二分有序数列上的元素,直到查找到的元素符合条件为止.
#include <iostream>
using namespace std;

typedef struct


{
int low,high;
int dp;
}node;

const int MAXN=100020;
const int Lmax=INT_MAX;

node Tree[MAXN<<2];
int hash[22][MAXN];


inline void Msort(int ind,int dp,int low,int high)


{
Tree[ind].dp=dp;
Tree[ind].low=low;
Tree[ind].high=high;

if (Tree[ind].low==Tree[ind].high)

{
return;
}

int mid=(low+high)>>1;

Msort(ind<<1,dp+1,low,mid);
Msort((ind<<1)+1,dp+1,mid+1,high);


int i,j;
int inds=low;

for (i=low,j=mid+1;i<=mid&&j<=high;)

{
if (hash[dp+1][i]<hash[dp+1][j])

{
hash[dp][inds++]=hash[dp+1][i++];
}
else

{
hash[dp][inds++]=hash[dp+1][j++];
}
}

if (i<=mid)

{
for (;i<=mid;)

{
hash[dp][inds++]=hash[dp+1][i++];
}
}

if (j<=high)

{
for (;j<=high;)

{
hash[dp][inds++]=hash[dp+1][j++];
}
}

}


inline int rank(int ind,int res,int low,int high)


{
int dp=Tree[ind].dp;

int mid,rs=low-1;

while (low<=high)

{
mid=(low+high)>>1;
if (hash[dp][mid]<res)

{
rs=mid,low=mid+1;
}
else

{
high=mid-1;
}
}
return rs-Tree[ind].low+1;
}

inline int query(int ind,int res,int low,int high)


{
if (Tree[ind].low==low&&Tree[ind].high==high)

{
return rank(ind,res,low,high);
}

int mid=(Tree[ind].low+Tree[ind].high)>>1;

if (low>mid)

{
return query((ind<<1)+1,res,low,high);
}

if (high<=mid)

{
return query(ind<<1,res,low,high);
}

return query(ind<<1,res,low,mid)+query((ind<<1)+1,res,mid+1,high);

}

inline bool check(int res,int low,int high,int k)


{
int rs=query(1,res,low,high);
return rs<k;
}

int main()


{
int T;
scanf("%d",&T);

while (T--)

{
int n,m;
int s,t,k;
scanf("%d%d",&n,&m);

int i;

for (i=1;i<=n;++i)

{
scanf("%d",&hash[0][i]);
}

int c=n-1;
int dp=0;

while (c)

{
c>>=1;
++dp;
}

for (i=dp;i>=0&&i>=dp-2;--i)

{
memcpy(hash[i]+1,hash[0]+1,n<<2);
}

Msort(1,0,1,n);

int low,high,res;

while(m--)

{
scanf("%d%d%d",&s,&t,&k);
low=1,high=n,res=Lmax;

while (low<=high)

{
int mid=(low+high)>>1;

if (check(hash[0][mid],s,t,k))

{
res=mid;
low=mid+1;
}
else

{
high=mid-1;
}

}
printf("%d\n",hash[0][res]);
}


}
return 0;
}