您的位置:首页 > 其它

hdu 2665 Kth number(线段树+归并树+二分)

2012-03-07 22:21 323 查看
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 100005
#define maxd 21
struct seg{
int l,r,m;
}tr[maxn<<2];
int s[maxn],segt[maxd][maxn<<2],n;
void build(int l,int r,int rt,int d){
tr[rt].l=l;
tr[rt].r=r;
tr[rt].m=(l+r)>>1;
int m=tr[rt].m;
if(l==r){
segt[d][l]=s[l];
return ;
}

build(l,m,rt<<1,d+1);
build(m+1,r,rt<<1|1,d+1);

int i=l,j=m+1,k=l;
while(i<=m && j<=r){//数值的归并
if(segt[d+1][i]>segt[d+1][j])
segt[d][k++]=segt[d+1][j++];
else
segt[d][k++]=segt[d+1][i++];
}
while(i<=m)
segt[d][k++]=segt[d+1][i++];
while(j<=r)
segt[d][k++]=segt[d+1][j++];

}
int countsig(int l,int r,int rt,int key,int d){//找出区间比其小的个数
return lower_bound(segt[d]+l,segt[d]+r+1,key)-(segt[d]+l);
}
int count(int l,int r,int rt,int key,int d){
if(tr[rt].l == l && tr[rt].r == r){
return countsig(l,r,rt,key,d);
}
int m=tr[rt].m;
if(r<=m)
return count(l,r,rt<<1,key,d+1);
else if(l>m)
return count(l,r,rt<<1|1,key,d+1);
else
return count(l,m,rt<<1,key,d+1)+count(m+1,r,rt<<1|1,key,d+1);
}
int query(int L,int R,int cnt){
int l=1,r=n;
while(l<=r){
int m=(l+r)>>1;
int t=count(L,R,1,segt[1][m],1);
if(t>=cnt)
r=m-1;
else
l=m+1;
}
return segt[1][l-1];
}
int main(){
int m;
while(~scanf("%d %d",&n,&m)){
for(int i=1;i<=n;i++)
scanf("%d",&s[i]);
build(1,n,1,1);
while(m--){
int l,r,cnt;
scanf("%d %d %d",&l,&r,&cnt);
printf("%d\n",query(l,r,cnt));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: