树状数组求第K小元素

来源:互联网 发布:剑三正太数据 编辑:程序博客网 时间:2024/04/28 23:20

求第K小元素有类似于qsort的分治算法,但时间复杂度是O(n)的,如果在线求的话耗时可能比较长,前几天听了Fallingflowers大牛讲的用树状数组求区间第K小元素,感触很深,这种算法的时间复杂度是O(log(n))的,如果要求在线计算的话显然很有优势。

基本思路是:

先开一个数组,其中记录某个数出现次数,每输入一个树,相当于将该数出现次数加1,对应到树状数组中就相当于insert(t, 1),统计的时候,可以利用树状数组的求和,既可以二分枚举,也可以利用数的二进制表示,下面的代码有效地利用了数的二进制表示。

 

 

 

 

以下是某位大牛的代码:

 

 

#include <iostream>
using namespace std;

#define maxn 1<<20
int n,k;
int c[maxn];

int lowbit(int x){
    
return x&-x;
}

void insert(int x,int t){
       
while(x<maxn){
          c[x]
+=t;
          x
+=lowbit(x);    
       }
}
int find(int k){
    
int cnt=0,ans=0;
    
for(int i=20;i>=0;i--){
        ans
+=(1<<i);
        
if(ans>=maxn || cnt+c[ans]>=k)ans-=(1<<i);
        
else cnt+=c[ans];
    }
    
return ans+1;
}
void input(){
       memset(c,
0,sizeof(c));
       
int t;
       scanf(
"%d%d",&n,&k);
       
for(int i=0;i<n;i++){    
            scanf(
"%d",&t);
            insert(t,
1);
       }
       printf(
"%d/n",find(k));
}
int main(){
    
int cases;
    scanf(
"%d",&cases);
    
while(cases--){
        input();
    }
    
return 0;
}