• hdu 2665 Kth number


    划分树

     1 /*
     2 HDU  2665 Kth number
     3 划分树
     4 
     5 
     6 */
     7 
     8 
     9 #include<stdio.h>
    10 #include<iostream>
    11 #include<string.h>
    12 #include<algorithm>
    13 using namespace std;
    14 
    15 const int MAXN=100010;
    16 int tree[30][MAXN];//表示每层每个位置的值
    17 int sorted[MAXN];//已经排序的数
    18 int toleft[30][MAXN];//toleft[p][i]表示第i层从1到i有多少个数分入左边
    19 
    20 void build(int l,int r,int dep)
    21 {
    22     if(l==r)return;
    23     int mid=(l+r)>>1;
    24     int same=mid-l+1;//表示等于中间值而且被分入左边的个数
    25     for(int i=l;i<=r;i++)
    26       if(tree[dep][i]<sorted[mid])
    27          same--;
    28     int lpos=l;
    29     int rpos=mid+1;
    30     for(int i=l;i<=r;i++)
    31     {
    32         if(tree[dep][i]<sorted[mid])//比中间的数小,分入左边
    33              tree[dep+1][lpos++]=tree[dep][i];
    34         else if(tree[dep][i]==sorted[mid]&&same>0)
    35         {
    36             tree[dep+1][lpos++]=tree[dep][i];
    37             same--;
    38         }
    39         else  //比中间值大分入右边
    40             tree[dep+1][rpos++]=tree[dep][i];
    41         toleft[dep][i]=toleft[dep][l-1]+lpos-l;//从1到i放左边的个数
    42 
    43     }
    44     build(l,mid,dep+1);
    45     build(mid+1,r,dep+1);
    46 
    47 }
    48 
    49 
    50 //查询区间第k大的数,[L,R]是大区间,[l,r]是要查询的小区间
    51 int query(int L,int R,int l,int r,int dep,int k)
    52 {
    53     if(l==r)return tree[dep][l];
    54     int mid=(L+R)>>1;
    55     int cnt=toleft[dep][r]-toleft[dep][l-1];//[l,r]中位于左边的个数
    56     if(cnt>=k)
    57     {
    58         //L+要查询的区间前被放在左边的个数
    59         int newl=L+toleft[dep][l-1]-toleft[dep][L-1];
    60         //左端点加上查询区间会被放在左边的个数
    61         int newr=newl+cnt-1;
    62         return query(L,mid,newl,newr,dep+1,k);
    63     }
    64     else
    65     {
    66          int newr=r+toleft[dep][R]-toleft[dep][r];
    67          int newl=newr-(r-l-cnt);
    68          return query(mid+1,R,newl,newr,dep+1,k-cnt);
    69     }
    70 }
    71 
    72 
    73 int main()
    74 {
    75     //freopen("in.txt","r",stdin);
    76     //freopen("out.txt","w",stdout);
    77     int T;
    78     int n,m;
    79     int s,t,k;
    80     scanf("%d",&T);
    81     while(T--)
    82     {
    83         scanf("%d%d",&n,&m);
    84         memset(tree,0,sizeof(tree));//这个必须
    85         for(int i=1;i<=n;i++)//从1开始
    86         {
    87             scanf("%d",&tree[0][i]);
    88             sorted[i]=tree[0][i];
    89         }
    90         sort(sorted+1,sorted+n+1);
    91         build(1,n,0);
    92         while(m--)
    93         {
    94             scanf("%d%d%d",&s,&t,&k);
    95             printf("%d
    ",query(1,n,s,t,0,k));
    96         }
    97     }
    98     return 0;
    99 }
  • 相关阅读:
    数组实战---集合了一些常用函数
    PHP正则表达式函数
    ThinkPHP学习之-------视图
    ThinkPHP小技巧之改变应用名称
    ThinkPHP中常用总结一CURD操作
    PHPExcel从数据库导出数据
    用PHP脚本来拆分字符串并形成两个新字段
    PHPExcel导出数据的基本使用方法
    php 中文切割字符串长度
    Nginx 在configure时的参数
  • 原文地址:https://www.cnblogs.com/tsw123/p/4437407.html
Copyright © 2020-2023  润新知