例题:http://poj.org/problem?id=2104


 最近可能是念念不忘,必有回响吧,总是看到区间第k大的问题,第一次看到是在知乎上有人面试被弄懵了后来又多次在比赛中看到。以前大概是知道怎么解决但是没有实际操作过。直到昨天看到了POJ上的2104题,一个标准的区间第K大询问,然后好好总结了一下区间第K大的问题。

 

普通人要是没想过这个问题,突然被问到第一个反应肯定和知乎上面试的哥们儿一样,把区间里面的所有数拎出来,排序,找第K个,但是这样时间复杂度是很大的,如果m次询问,时间复杂度是O( m×(n + n×logn) )要是询问次数m非常大时间复杂度很恐怖。

 

要是优化就有很多种方法,第一种就是利用分治的思维,分块。将n个数分成√n × logn  块,然后对每个块进行排序。既然是区间第K大,那假设N是区间内第K大的数,那么不大于N的数至少有K个。这样对N值进行二分枚举,每枚举出一个N值,然后去区间中找不大于N的数。因为对于每个块都是排好序的,所以如果该块完全包含在区间内,就直接对块进行二分查找不大于N的数有多少个。块部分包含在区间内的就直接暴力查找(过程如图1.1所示)。根据查找的值再扩大或者缩小N值。

                     解决区间第K大的问题的各种方法

                   图1.1  

这个时候时间复杂度就是O( n×logn + m√nlog1.5n)

 

 1 void init() {
 2     scanf("%d%d",&n,&m);//n个数m次询问
 3     unit = 1000;//分块大小
 4     for(ll i=0;i<n;i++) {
 5         scanf("%d",&num[i]);
 6         OdrArr[i] = num[i];
 7         ve[i/unit].push_back(num[i]);//分别装入块中
 8     }
 9     for(ll i=0;i<n/unit;i++)//最后一个块不用排序
10         sort(ve[i].begin(),ve[i].end());//对每个块排序
11     sort(OdrArr, OdrArr+n);//二分枚举N值
12 }
初始化分块

相关文章:

  • 2021-12-21
  • 2021-12-17
  • 2021-07-15
  • 2021-12-18
  • 2022-12-23
  • 2021-07-17
  • 2022-02-15
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-12-03
  • 2022-02-28
  • 2022-12-23
相关资源
相似解决方案