poj1727 排序+二分搜索
2014-03-12 08:19
232 查看
/** * 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值下,至少需要的点数是否<=m bool 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; }
相关文章推荐
- POJ 2785 4 Values whose Sum is 0(排序+二分搜索)
- Subsequence 【poj-3061】【二分搜索】
- Java使用分治算法实现排序数索引功能示例【二分搜索】
- 【POJ】3122 Pie 二分搜索
- POJ 3104&&POJ 2976 继续二分搜索。。。
- poj 3977 折半枚举二分搜索
- POJ 3662 Telephone Lines (SPFA、二分搜索)
- POJ 3273 Monthly Expense (二分搜索)
- POJ 1064 1759 3484 3061 (二分搜索)
- POJ 2002 Squares 几何 + 二分搜索 或 hash
- POJ 1759 - Garland(二分搜索)
- POJ 3104 Drying 二分搜索
- POJ 1727 Advanced Causal Measurements (ACM) (二分+贪心)
- poj 1759 Garland 二分搜索
- 二分搜索求最大值最小化--poj2456
- POJ 3579 Median (二分搜索)
- 《挑战程序设计竞赛》3.1.1 二分搜索-最大化最小值 POJ1064 2456 3258 3273 3104 3045
- POJ - 2456 Aggressive cows(二分搜索:最大化最小值)
- 排序和搜索(二)——python实现二分查找
- POJ - 2976 Dropping tests(二分搜索:最大化平均值)