HDU_4251_The Famous ICPC Team Again(划分树)

来源:互联网 发布:jquery json数组遍历 编辑:程序博客网 时间:2024/06/06 20:02

题型:数据结构


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


分析:

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

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


代码:

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>using namespace std;const int N = 123456;int n;int arr[N];//原数据,下标从 1 开始int sortedPos[N];//排序后int lfnum[32][N];//元素所在区间的当前位置进入左孩子的元素的个数int val[32][N];//记录第 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)]]);        }    }}


0 0
原创粉丝点击