zoukankan      html  css  js  c++  java
  • 【转载】【树状数组区间第K大/小】

    原帖:http://www.cnblogs.com/zgmf_x20a/archive/2008/11/15/1334109.html

    回顾树状数组的定义,注意到有如下两条性质:
    一,c[ans]=sum of A[ans-lowbit(ans)+1 ... ans];
    二,当ans=2^k时,
     c[ans]=sum of A[1 ... ans];

    下面说明findK(k)如何运作:
    1,设置边界条件ans,ans'<maxn且cnt<=k;
    2,初始化cnt=c[ans],其中ans=2^k且k为满足边界条件的最大整数;
    3,找到满足边界条件的最大的ans'使得ans'-lowbit(ans')=ans,即ans'满足c[ans']=A[ans+1 .. ans'](根据性质一),只要将c[ans']累加到cnt中(此时cnt=sum of A[1 ... ans'],根据性质二),cnt便可以作为k的逼近值;
    4,重复第3步直到cnt已无法再逼近k,此时ans刚好比解小1,返回ans+1。

    因此findk(k)的实质就是二分逼近

     1 /**********************************
     2 
     3 树状数组实现查找K小的元素
     4 
     5                   经典。
     6 
     7 限制:数据范围在1<<20 以内
     8 
     9 ***********************************/
    10 
    11 #include <iostream>
    12 
    13 using namespace std;
    14 
    15 
    16 
    17 #define maxn 1<<20
    18 
    19 int n,k;
    20 
    21 int c[maxn];
    22 
    23 
    24 
    25 int lowbit(int x){
    26 
    27     return x&-x;
    28 
    29 }
    30 
    31 
    32 
    33 void insert(int x,int t){
    34 
    35        while(x<maxn){
    36 
    37           c[x]+=t;
    38 
    39           x+=lowbit(x);    
    40 
    41        }
    42 
    43 }
    44 
    45 int find(int k){
    46 
    47     int cnt=0,ans=0;
    48 
    49     for(int i=20;i>=0;i--){
    50 
    51         ans+=(1<<i);
    52 
    53         if(ans>=maxn || cnt+c[ans]>=k)ans-=(1<<i);
    54 
    55         else cnt+=c[ans];
    56 
    57     }
    58 
    59     return ans+1;
    60 
    61 }
    62 
    63 void input(){
    64 
    65        memset(c,0,sizeof(c));
    66 
    67        int t;
    68 
    69        scanf("%d%d",&n,&k);
    70 
    71        for(int i=0;i<n;i++){    
    72 
    73             scanf("%d",&t);
    74 
    75             insert(t,1);
    76 
    77        }
    78 
    79        printf("%d
    ",find(k));
    80 
    81 }
    82 
    83 int main(){
    84 
    85     int cases;
    86 
    87     scanf("%d",&cases);
    88 
    89     while(cases--){
    90 
    91         input();
    92 
    93     }
    94 
    95     return 0;
    96 
    97 }
    View Code
  • 相关阅读:
    局域网共享磁盘或文件夹访问
    Android实例-退出程序
    delphi 合并两个 Wav 文件流的函数
    Delphi数据库处理
    cxgrid的FINDPANEL编程
    Python之路【目录】
    Delphi TreeView – 自动展开树形结构
    Delphi TreeView – 自动给标题上加图片
    Delphi 发送邮件 通过Office Outlook
    Delphi Create(nil), Create(self), Create(Application)的区别
  • 原文地址:https://www.cnblogs.com/hoskey/p/4320419.html
Copyright © 2011-2022 走看看