您的位置:首页 > 大数据 > 人工智能

HDU_4251_The Famous ICPC Team Again(划分树)

2014-07-19 10:22 330 查看
题型:数据结构

题意:n个数,m次查询,每次查询区间的中位数。

分析:

赤果果的模板题,知道的就过,不知道的就只能喝茶了。

划分树,即求区间第K大数

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 123456;

int n;
int arr
;//原数据,下标从 1 开始
int sortedPos
;//排序后
int lfnum[32]
;//元素所在区间的当前位置进入左孩子的元素的个数
int val[32]
;//记录第 k 层当前位置的元素的值
bool cmp(const int &x,const int &y) {
return arr[x]<arr[y];
}
void build(int l,int r,int d) {
if(l==r) return;
int mid=(l+r)>>1,p=0;
for(int i=l; i<=r; i++) {
if(val[d][i]<=mid) {
val[d+1][l+p]=val[d][i];
lfnum[d][i]=++p;
} else {
lfnum[d][i]=p;
val[d+1][mid+i+1-l-p]=val[d][i];
}
}
build(l,mid,d+1);
build(mid+1,r,d+1);
}
//求区间[s,e]第 k 大的元素
int query(int s,int e,int k,int l=1,int r=n,int d=0) {
if(l==r) return l;
int mid=(l+r)>>1,ss,ee;
ss=(s==l?0:lfnum[d][s-1]);
ee=lfnum[d][e];
if(ee-ss>=k) return query(l+ss,l+ee-1,k,l,mid,d+1);
return query(mid+1+(s-l-ss),mid+1+(e-l-ee),k-(ee-ss),mid+1,r,d+1);
}
int main() {
int cas=0,m,l,r,k;
while(scanf("%d",&n)!=EOF) {
for(int i=1; i<=n; i++) {
scanf("%d",arr+i),sortedPos[i]=i;
}
sort(sortedPos+1,sortedPos+n+1,cmp);
for(int i=1; i<=n; i++) {
val[0][sortedPos[i]]=i;
}
build(1,n,0);
printf("Case %d:\n",++cas);
scanf("%d",&m);
while(m--) {
scanf("%d%d",&l,&r);
k = (r-l+2)/2;
printf("%d\n",arr[sortedPos[query(l,r,k)]]);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: