干掉这道题的那一刻,我只想说:我终于**的AC了!!!

最终内存1344K,耗时10282ms,比起归并树、划分树以及其他各种黑科技,这个成绩并不算光彩⊙﹏⊙

但至少,从最初的无数次TLE到最终的AC,这过程见证了一个二分算法的艰辛优化

感谢国家,感谢XXTV,感谢《挑战程序设计竞赛》~( ̄▽ ̄)~*

先贴代码:

 ;
 ;
 ;
 ;
 const int maxV=1e9;

 int bucket[bktCount][bktSize];
 int unOrdered[bktSize*bktCount];
 int ordered[bktSize*bktCount];
 int N,K;

 #include <cstdio>
 #include <cstring>
 #include <algorithm>

 void init()
 {
     scanf("%d%d",&N,&K);
     memset(bucket[N>>bktDigit],0x7f,sizeof(bucket[N>>bktDigit]));
     ;i<N;i++)
     {
         scanf("%d",unOrdered+i);
         ordered[i]=unOrdered[i];
         bucket[i>>bktDigit][i&bktMaxIdx]=unOrdered[i];
     }

     using std::sort;
     int bktUsed=N>>bktDigit;
     sort(ordered,ordered+N);
     ;i<=bktUsed;i++) sort(bucket[i],bucket[i]+bktSize);
 }

 inline void enumerate(int _rangeL,int _rangeR,int _val,int& _notMore)
 {
     for(int i=_rangeL;i<=_rangeR;i++)
         if(unOrdered[i]<=_val) ++_notMore;
 }

 inline void countBucket(int _bktIdx,int _val,int& _notMore)
 {
     using std::upper_bound;

     int* ub=upper_bound(bucket[_bktIdx],bucket[_bktIdx]+bktSize,_val);
     _notMore+=(ub-bucket[_bktIdx]);
 }

 int ask(int _rangeL,int _rangeR,int _k) //k-th smallest
 {
     int digitL=_rangeL>>bktDigit;
     int digitR=_rangeR>>bktDigit;
     ;
     ;

     while(vL<vR)
     {
         ;
         ;
         if(digitL==digitR)
             enumerate(_rangeL,_rangeR,ordered[midV],notMore);
         else
         {
             ;i<digitR;i++)
                 countBucket(i,ordered[midV],notMore);
             enumerate(_rangeL,((digitL+)<<bktDigit)-,ordered[midV],notMore);
             enumerate(digitR<<bktDigit,_rangeR,ordered[midV],notMore);
         }

         ;
         else vR=midV;
     }
     return ordered[vL];
 }

 int main()
 {
     init();
     ;i<K;i++)
     {
         int l,r,k;
         scanf("%d%d%d",&l,&r,&k);
         printf(,r-,k));
     }
     ;
 }

1、为什么统计notMore,而不是统计less或者两者都统计?

二分的过程中,缩减区间的关键是:

1、必须使可能成为最终解的值保留在二分区间中

2、每一次都必须使区间大小的确被缩减,以防陷入死循环

在这道题中,某个值x为解的条件是:less(x)<x && notMore(x)>=x

如果统计Less的话,上面的代码很难是保证第一条的

而如果两者都统计的话,表面上当x满足条件时即可跳出,可以减少二分所需的时间

但是事实上,这样做的代价就是统计的时间复杂度常数乘以2,总的来说得不偿失(会TLE)

2、二分的对象是什么?可否把maxValue和minValue作为二分的对象?

Answer:NO!!!

正确的做法是将原数组排好序,然后对这个有序数组二分

理由很简单:范围小。二分区间长不会超过1e5

如果对数值本身二分的话,minValue和maxValue最坏时分别会达到-1e9和+1e9,二分的时间代价是前者的1.9倍

3、平方分割必须是严格的么?

Answer:NO(*^__^*)(论如何用标点和颜文字表达语气( ̄. ̄))

设数据规模为N,每个桶的大小为B,则单次询问的时间复杂度为: O ( (N / B ) * log B + B )

当B = O ( ( N * log N ) ^ 0.5 ) 时,总的时间复杂度会比严格的平方分割小一些

代码中将B取为了1024正是为此。(顺便也方便了位运算)

B取512时效率会相对变差,B取256时干脆TLE

这道题更好的做法是归并树,比归并树还好的做法是划分树,不过这都是后话了,有时间慢慢填坑

最新文章

  1. MVC5在Mono上的各种坑
  2. 7. LAMP环境搭建
  3. JSP文件下载
  4. python学习笔记--导入tab键自动补全功能的配置
  5. Warm up 2
  6. paip.输入法编程---智能动态上屏码儿长调整--.txt
  7. zoj 1149 Dividing
  8. MySQL常用命令总结2
  9. javascript编程解决黑白卡片问题
  10. XWPFDocument创建和读取Office Word文档基础篇(一)
  11. python 全栈开发,Day3(正式)
  12. REACT相关资料合集
  13. shell编程 之 文件包含
  14. 【FM】算法
  15. 【mongodb】如何在mac上安装mongoDB
  16. CUDA[4] sample program: matrix-vector multiplication
  17. java泛型中&lt;?&gt;和&lt;T&gt;区别
  18. word设置行距18磅
  19. &lt;--------------------------构造方法------------------------------&gt;
  20. 正则表达式——WPF输入控件TextBox 限定输入特定字符

热门文章

  1. What version of .NET Framework is integrated into what version of OS?
  2. TFS 2012使用简介(一)
  3. Linux学习笔记29——IPC状态命令
  4. HDOJ/HDU 1250 Hat&#39;s Fibonacci(大数~斐波拉契)
  5. 《Linear Algebra and Its Applications》-chaper5-特征值与特征向量-基本概念
  6. lightoj1057 - Collecting Gold (tsp问题)
  7. lightoj 1030 概率dp
  8. nyoj 95 众数问题【水】
  9. [置顶] MyEclipse下安装插件方法(properties文件编辑器Propedit为例)
  10. 转:实现Java Web程序的自动登录