第一次写归并排序+线段树 感觉受益颇深
这道题是求在[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;
}