poj1727 排序+二分搜索
来源:互联网 发布:泉州数据分析培训 编辑:程序博客网 时间:2024/06/06 03:08
/** * poj1727 排序+二分 * 类似题目的附图,在每个点以正负1为斜率作直线,两条直线以下的点就可以作为它的因果点 * 最大值就是所有点中最小的纵坐标;最小值,是最左的-1斜率直线与最右的+1斜率直线的交点 * 对符合范围的t进行二分定位,每一级t计算能覆盖所有输入点的最小点数count,如果count > m则向上查找,反之向下查找。最后输出的就是满足count <= m的最大t值 * 为了方便搜索,需要预先对所有点进行排序,排序的依据是,过该点的斜率为1的直线与x轴相交的点的x坐标,升序排列。排序之后,所有点是以与t=t0的左交点为准升序排列 * count的计算有点像之前做过的一个dp题,每次记录一个覆盖区间,如果新的点在t=t0的覆盖段与记录的覆盖区间没有交点,那么启用新的覆盖区间,并count++;否则用二者的交集更新覆盖区间 * 注意,我这道题用cin读就会超时,改用scanf就过了 */#include <iostream>#include <stdlib.h>#include <cstdio>using namespace std;const int MAX_NUM = 100002;struct point{ int x; int t;} p[MAX_NUM];int n,m;//以与x轴交点的左边点为准,升序排列int cmp(const void* a,const void* b){ return ((*((point*)a)).x - (*((point*)a)).t) - ((*((point*)b)).x - (*((point*)b)).t);}//检查当前的t值下,至少需要的点数是否<=mbool check(int t){ int count = 1; int last_left,last_right; for(int i=1;i<=n;i++){ int left = t + p[i].x - p[i].t; int right = p[i].x + p[i].t - t; if(i == 1){ last_right = right; last_left = left; continue; } //如果左点与之前的区间不相交,那么自增count,维护一个新的区间 if(left > last_right){ count ++; last_right = right; last_left = left; } //如果当前点的区间完全在之前区间内部,区间是缩小了,以当前点区间为备选区间 else if(last_left <= left && last_right >= right){ last_right = right; last_left = left; } //如果当前点的区间是与之前区间部分相交,那么只更新左点,以相交区间作为新的备选区间 else if(last_left <= left && left <= last_right && last_right <= right){ last_left = left; } if(count > m){ return false; } } return true;}int main(){ int max_times; cin >> max_times; for(int times = 1;times <= max_times;++times){ int min_t = 99999999,search_top,search_bottom,leftest = 99999999,rightest = -99999999; cin >> n >> m; for(int i=1;i<=n;++i){ //cin >> p[i].t >> p[i].x; scanf("%d%d",&p[i].t,&p[i].x); if(min_t > p[i].t){ min_t = p[i].t; } leftest = (leftest > (p[i].t + p[i].x)) ? (p[i].t + p[i].x) : leftest; rightest = (rightest < (p[i].x - p[i].t)) ? (p[i].x - p[i].t) : rightest; } search_top = min_t; search_bottom = (rightest - leftest) / (-2); //sort qsort(p+1,n,sizeof(point),cmp); //half deviding!! int top = search_top, bottom = search_bottom, ans; while(top >= bottom){ int search_t = (top + bottom) / 2; //如果这一层的点数不够,则向上查找 if(check(search_t)){ ans = search_t;//最大的点数不够的点满足条件 bottom = search_t + 1; } //如果这一层的点数太多,则向下查找 else{ top = search_t - 1; } } cout << "Case " << times << ": " << ans << endl; } return 0;}
0 0
- poj1727 排序+二分搜索
- 二分搜索.合并排序
- 冒泡排序+二分搜索
- 二分排序:直接插入排序+二分搜索
- poj 2785 排序+二分搜索
- 二分排序(搜索)树
- 选择排序,冒泡排序,二分搜索,插入排序,归并排序
- 二分搜索算法和快速排序算法
- 动态数组 选择排序 二分搜索技术
- 快速排序算法和二分搜索算法
- 基于二分搜索的插入排序
- 二分搜索树排序binary search sorting的c++实现
- uva 10474 - Where is the Marble?(排序,二分搜索)
- Java 分治算法实现排序数索引(二分搜索)
- 【OI之路】04排序搜索-1二分
- 51nod 1421 最大mod值 (排序+二分搜索)
- 二分搜索
- 二分搜索
- ExtJs 集成kindeditor
- visudo精确用户赋权(sudo)
- poj1723 排序+中位数
- MATLAB R2009b安装破解
- Android 4.4 Kitkat Phone工作流程浅析(三)__MO(去电)流程分析
- poj1727 排序+二分搜索
- poj1731 next_permutation
- poj1732 DP
- 查找文件夹下特定后缀名的文件,返回列表。
- i386中的状态和控制寄存器
- nodejs总结
- html5本地存储的兼容性写法
- poj1745 0-1DP
- poj1830 高斯消元法