POJ2104 K-th Number 静态区间第k最值 平方分割
干掉这道题的那一刻,我只想说:我终于**的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
这道题更好的做法是归并树,比归并树还好的做法是划分树,不过这都是后话了,有时间慢慢填坑
POJ2104 K-th Number 静态区间第k最值 平方分割的更多相关文章
- POJ2104 K-th Number —— 静态区间第k小
题目链接:http://poj.org/problem?id=2104 K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Sub ...
- poj2104&&poj2761 (主席树&&划分树)主席树静态区间第k大模板
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 43315 Accepted: 14296 Ca ...
- HDU3473--Minimum Sum(静态区间第k大)
Minimum Sum Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tota ...
- 数据结构2 静态区间第K大/第K小
给定数组$A[1...N]$, 区间$[L,R]$中第$K$大/小的数的指将$A[L...R]$中的数从大到小/从小到大排序后的第$K$个. "静态"指的是不带修改. 这个问题有多 ...
- Dynamic Rankings || 动态/静态区间第k小(主席树)
JYF大佬说,一星期要写很多篇博客才会有人看 但是我做题没有那么快啊QwQ Part1 写在前面 区间第K小问题一直是主席树经典题=w=今天的重点是动态区间第K小问题.静态问题要求查询一个区间内的第k ...
- 主席树初步学习笔记(可持久化数组?静态区间第k大?)
我接触 OI也快1年了,然而只写了3篇博客...(而且还是从DP跳到了主席树),不知道我这个机房吊车尾什么时候才能摸到大佬们的脚后跟orz... 前言:主席树这个东西,可以说是一种非常畸形的数据结构( ...
- 静态区间第k大(归并树)
POJ 2104为例 思想: 利用归并排序的思想: 建树过程和归并排序类似,每个数列都是子树序列的合并与排序. 查询过程,如果所查询区间完全包含在当前区间中,则直接返回当前区间内小于所求数的元素个数, ...
- 主席树学习笔记(静态区间第k大)
题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输出 ...
- 主席树(静态区间第k大)
前言 如果要求一些数中的第k大值,怎么做? 可以先就这些数离散化,用线段树记录每个数字出现了多少次. ... 那么考虑用类似的方法来求静态区间第k大. 原理 假设现在要有一些数 我们可以对于每个数都建 ...
随机推荐
- poj2151
求每只队伍都回答出题目,且至少有一只队伍回答出n道题的概率存在性问题我们可以转化为任意性问题用P(每支队伍都回答出题目)-P(每只队伍回答的题目数小于n)然后我们可以递推求解 ..,..,..] of ...
- css背景图片位置:background的position
position的两个参数:水平方向的位置,垂直方向的位置----------该位置是指背景图片相对于前景对象的 1.background:url(../image/header.jpg) no-re ...
- 【动态规划】天堂(Heaven) 解题报告
天堂(heaven) 题目描述 每一个要上天堂的人都要经历一番考验,当然包括小X,小X开始了他进入天堂的奇异之旅.地狱有18层,天堂竟然和地狱一样,也有很多很多层,天堂共有N层.从下到上依次是第1,2 ...
- hdu 4414 暴力枚举
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> #i ...
- Django中的Form
Form 一.使用Form Django中的Form使用时一般有两种功能: 1.生成html标签 2.验证输入内容 要想使用django提供的form,要在views里导入form模块 from dj ...
- C#执行参数为游标 返回一个记录集的Oracle存储过程
public DataTable SelectPay_Unit() { string returns = ""; DataTable objDataTable = new Data ...
- 实现网页页面跳转的几种方法大全(meta标签、js实现、php实现)
1.meta标签实现 只需在head里加上下面这一句就行了,在当前页面停留0.1秒后跳转到目标页面 代码如下 复制代码 1 <meta http-equiv="refresh&quo ...
- IntelliJ IDEA自用快捷键 转载
最常用快捷键- 未分类 command Binding Description defeat - Ctrl+/ 代码提示 No - Ctrl+Alt+L 格式化代码 - Ctrl+B 快速打开光标 ...
- thinkphp中使用PHPEXCEL导入数据
导入方法比较简单 但必须考虑到Excel本身单元格格式问题 例如以0开头的字符串读出来被去掉了前导0 成为float型而丢失一位 必须进行处理 <?php /** * Author lizhao ...
- NIO与普通IO文件读写性能对比
最近在熟悉java的nio功能.nio采用了缓冲区的方式进行文件的读写,这一点更接近于OS执行I/O的方式.写了个新旧I/O复制文件的代码,练练手,顺便验证一下两者读写性能的对比,nio是否真的比普通 ...