• 求序列中第k大的元素(划分树模板)


    http://acm.hdu.edu.cn/showproblem.php?pid=4251

    n个数,求给定区间中间大小的元素的值

    Sample Input
    5
    5 3 2 4 1
    3
    1 3
    2 4
    3 5
    5
    10 6 4 8 2
    3
    1 3
    2 4
    3 5
    Sample Output
    Case 1:
    3
    3
    2
    Case 2:
    6
    6
    4
     1 #include<cstdio>
     2 #include<string>
     3 #include<vector>
     4 #include<algorithm>
     5 #define N 100009
     6 using namespace std;
     7 int n;
     8 int arr[N];//原数据
     9 int od[N];//排序后
    10 int lfnum[20][N];//元素所在区间的当前位置进入左孩子的元素的个数
    11 int val[20][N];//记录第k层当前位置的元素的值
    12 bool cmp(const int &x,const int &y){return arr[x]<arr[y];}
    13 void build(int l,int r,int d)
    14 {
    15     if(l==r) return;
    16     int mid=(l+r)>>1,p=0;
    17     for(int i=l;i<=r;i++)
    18     {
    19         if(val[d][i]<=mid)
    20         {
    21             val[d+1][l+p]=val[d][i];
    22             lfnum[d][i]=++p;
    23         }
    24         else
    25         {
    26             lfnum[d][i]=p;
    27             val[d+1][mid+i+1-l-p]=val[d][i];
    28         }
    29     }
    30     build(l,mid,d+1);
    31     build(mid+1,r,d+1);
    32 }
    33 //求区间[s,e]第k大的元素
    34 int query(int s,int e,int k,int l=1,int r=n,int d=0)
    35 {
    36     if(l==r) return l;
    37     int mid=(l+r)>>1,ss,ee;
    38     ss=(s==l?0:lfnum[d][s-1]);
    39     ee=lfnum[d][e];
    40     if(ee-ss>=k) return query(l+ss,l+ee-1,k,l,mid,d+1);
    41     return query(mid+1+(s-l-ss),mid+1+(e-l-ee),k-(ee-ss),mid+1,r,d+1);
    42 }
    43 int main()
    44 {
    45     int cas=0,m,l,r;
    46     while(scanf("%d",&n)!=EOF)
    47     {
    48         printf("Case %d:\n",++cas);
    49         for(int i=1;i<=n;i++) scanf("%d",arr+i),od[i]=i;
    50         sort(od+1,od+n+1,cmp);
    51         for(int i=1;i<=n;i++) val[0][od[i]]=i;
    52         build(1,n,0);
    53         scanf("%d",&m);
    54         while(m--)
    55         {
    56             int num,k;
    57             scanf("%d%d",&l,&r);
    58             k=(r-l)/2+1;//中间大小
    59             num=query(l,r,k);
    60             int ans=arr[od[num]];
    61             printf("%d\n",ans);
    62         }
    63     }
    64 }
  • 相关阅读:
    安卓学习-其他-网络状态工具
    安卓学习-界面-ui-Notification
    安卓学习-界面-ui-ScrollView和HorizontalScrollView
    安卓学习-界面-ui-TabHost
    安卓学习-界面-ui-SearchView
    OpecnCV训练分类器详细整理
    OopenCV复习及函数深入理解(轮廓查询及绘图)
    ASP.NET基础学习未整理随笔
    C#或ASP.NET绘图初探
    ASP.NET基础学习(暴力破解密码)
  • 原文地址:https://www.cnblogs.com/qijinbiao/p/2594845.html
Copyright © 2020-2023  润新知