二分专题(不定期更新)
1、POJ 3258 River Hopscotch
题意:给出小溪的长度L,给出河中石头数N和最多可移动的石头数M,使得每两颗相邻石头、起点与第一颗石头、终点与最后一颗石头之间的最小距离最大。
思路:二分最小距离,然后把间距小于该距离的石头移除,如果移除的石头数大于M,说明该距离太大,否则可以尝试增大该距离。
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 int L, N, M; 5 int st, ed; 6 const int maxn = 50005; 7 int Rocks[maxn]; 8 bool Judge(int dis) 9 { 10 int rmvrocks = 0; 11 int tdis = 0; 12 int refpos = 0; 13 int tnumrocks = 0; 14 for (int i = 0; i < N;) 15 { 16 tnumrocks = 0; 17 while (i<N&&Rocks[i] - refpos < dis) tnumrocks++,i++; 18 rmvrocks += tnumrocks; 19 refpos = Rocks[i]; 20 i++; 21 } 22 if (tnumrocks == 0 && L - Rocks[N - 1] < dis) rmvrocks++; 23 if (rmvrocks > M) return false; 24 else return true; 25 } 26 int main() 27 { 28 while (cin >> L) 29 { 30 cin >> N >> M; 31 for (int i = 0; i < N; i++) cin >> Rocks[i]; 32 sort(Rocks, Rocks + N); 33 int mindis = Rocks[0]; 34 for (int i = 1; i < N; i++) 35 if (Rocks[i] - Rocks[i - 1] < mindis) mindis = Rocks[i] - Rocks[i - 1]; 36 if (L - Rocks[N - 1] < mindis) mindis = L - Rocks[N - 1]; 37 int l = mindis, r = L; 38 while (l <= r) 39 { 40 int mid = (l + r) / 2; 41 if (Judge(mid)) l = mid + 1; 42 else r = mid - 1; 43 } 44 cout << r << endl; 45 } 46 return 0; 47 }
View Code
2、POJ 3104 Drying
题意:给出n件衣服,每件衣服上都有wi的水分,每次要么把一件衣服放在烘炉上,每分钟至多减少k的水分,要么自然烘干,每分钟减少1的水分,同一时间最多只能把一件衣服放在烘炉上。求所有衣服都烘干的最小时间。
思路:二分总时间,记为为t,设此时所需用烘炉的时间为tx=0.为使总时间最小,那么要尽可能利用烘炉,直至所有衣服被烘干之前的每分钟都有把某一件衣服放在烘炉上,我们则统计出该时间,如果小于等于t,说明我们还可以尝试减少时间,否则,只能增大时间。接下来要统计出tx.第i件衣服的水分为wi.如果wi<t,则让其自然烘干即可;否则,由于只需要ceil((wi-x)/(k-1))的用烘炉的时间,剩下的水分让其自然烘干。
1 #include <iostream> 2 #include <algorithm> 3 #include <cmath> 4 #include <cstdio> 5 using namespace std; 6 #define MAXN 100000+10 7 #define LL long long 8 int n, k; 9 int wat[MAXN]; 10 11 bool Judge(int x) 12 { 13 LL t = 0; 14 for (int i = 0; i<n; i++) 15 { 16 if (wat[i]>x) 17 { 18 int xx = ceil((wat[i] - x)*1.0 / (k - 1)); 19 t += xx; 20 } 21 if (t>x)return false; 22 } 23 24 if (t>x)return false; 25 else return true; 26 } 27 int main() 28 { 29 while (~scanf("%d", &n)) 30 { 31 int l = 1, r = 0; 32 for (int i = 0; i<n; i++) 33 { 34 scanf("%d", &wat[i]); 35 r = max(r, wat[i]); 36 } 37 scanf("%d", &k); 38 39 if (k == 1) 40 { 41 printf("%d\n", r); 42 continue; 43 } 44 int mid = 0; 45 while (l <= r) 46 { 47 mid = (l + r) / 2; 48 if (Judge(mid)) 49 { 50 r = mid - 1; 51 } 52 else 53 l = mid + 1; 54 } 55 printf("%d\n",l); 56 } 57 return 0; 58 }
View Code
3、poj2976-Dropping tests(0-1分数规划)
题意:有n次测试,每次测试对ai道题,总共bi道题。现在,你可以在最多除去k次的测试,使得剩下的测试中总正确率(剩下测试的对的总题数/剩下测试的总题数)最高。
思路:二分总正确率,对于当前假设正确率x,对于每个测试,其额外做对的题目为ai-x*bi(也可以看成贡献度),然后去掉最小的k次,累加前面大的n-k次,如果算出来正确率可以超过x,则可以尝试增大x,否则,只能减小x.
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 const int maxn = 1010; 5 int n, k; 6 struct Score 7 { 8 int a; 9 int b; 10 }tests[maxn]; 11 long long suma, sumb; 12 13 double tt;//假设的当前正确率 14 bool Cmp(const Score&a, const Score&b) 15 { 16 return a.a - tt*a.b > b.a - tt*b.b;//对当前正确率贡献度大的排前面 17 } 18 19 bool Judge(double rt) 20 { 21 tt = rt; 22 sort(tests, tests + n, Cmp); 23 long long sum1 = 0, sum2 = 0; 24 for (int i = 0; i < n; i++) 25 { 26 if(i<n-k)sum1 += tests[i].a, sum2 += tests[i].b; 27 else if (tests[i].a - rt*tests[i].b > 1e-4) sum1 += tests[i].a, sum2 += tests[i].b; 28 } 29 if (1.0*sum1 / sum2 >= rt) return true; 30 else return false; 31 } 32 33 int main() 34 { 35 while (cin >> n >> k, n != 0 || k != 0) 36 { 37 suma = sumb = 0; 38 for (int i = 0; i < n; i++) 39 { 40 cin >> tests[i].a; 41 suma += tests[i].a; 42 } 43 for (int i = 0; i < n; i++) 44 { 45 cin >> tests[i].b; 46 sumb += tests[i].b; 47 } 48 double L = 1.0*suma / sumb; 49 double R = 1.0; 50 while (R - L > 1e-4) 51 { 52 double mid = (L + R) / 2; 53 if (Judge(mid)) L = mid; 54 else R = mid; 55 } 56 printf("%.lf\n", L*100); 57 } 58 return 0; 59 }
View Code
4、poj 3685 Matrix
题意:对于n*n的矩阵,第i行第j列的数字为i*i + 100000 * i + j*j - 100000 * j + i*j。求第m小的元素值。
思路:从式子可以看出每列中的数字按行递增。然后二分答案,然后对于每列二分,找到第一个大于等于该答案的位置,然后就可以知道该列中小于该答案的数字的个数。统计出所有的个数,如果个数大于m,说明该答案还可以减小,否则的话需要增大。
1 //先对答案进行二分,求满足小于等于该答案的个数(求法:由于每列从上到下的值递增,对每一列找到第一个大于答案的值,然后累加个数),若个数太多,则说明答案太大,否则太小。 2 #include<iostream> 3 #include<cstdio> 4 using namespace std; 5 const long long INF = 1LL << 50; 6 long long f(long long i, long long j) 7 { 8 return i*i + 100000 * i + j*j - 100000 * j + i*j; 9 } 10 long long n, m; 11 bool Judge(long long tans) 12 { 13 long long num = 0; 14 for (int j = 1; j <= n; j++) 15 { 16 int l = 1, r = n; 17 while (l <= r) 18 { 19 int mid = (l + r) / 2; 20 if (f(mid, j) > tans) 21 { 22 r = mid - 1; 23 } 24 else l = mid + 1; 25 } 26 num += l - 1; 27 } 28 if (num >= m) return true; 29 else return false; 30 } 31 int main() 32 { 33 int t; 34 cin >> t; 35 while (t--) 36 { 37 scanf("%lld%lld", &n, &m); 38 long long R = INF, L = -INF; 39 while (L <= R) 40 { 41 long long mid = (L + R) >> 1; 42 if (Judge(mid)) 43 { 44 R = mid - 1; 45 } 46 else L = mid + 1; 47 } 48 printf("%lld\n", L); 49 } 50 return 0; 51 }
View Code
5、poj 3662 Telephone Linse
题意:有N个电线杆,给出P条可以连接的电线,其中K条可以免费,求存在1到N的一条路径,若连接的电线数目小于K条,则为0;若大于,则求其除去K条电线后剩余的电线长度最大值的最小值;若不存在路径,为-1.
思路:最优情况下免费的K条肯定取需要连接的电线从大到小前K条。那么我们二分这个最大长度mid,把大于该长度的电线的权值记为1,小于等于该长度的电线的权值记为0,求一次从1开始的最短路径,dis[N]即为大于mid长度的电线条数,如果该条数小于等于K,说明我们至多需要支付mid的价格,接下来看能不能再缩小mid;否则,只能增大mid;如果不存在路径,直接输出-1;如果mid为0时dis[N]小于等于K,则可直接输出0.
1 #include<iostream> 2 #include<memory.h> 3 #include<vector> 4 #include<queue> 5 using namespace std; 6 struct node 7 { 8 int to; 9 int length; 10 int weight; 11 node(int t= 0, int l = 0,int wt=0):to(t),length(l),weight(wt){ } 12 }; 13 vector<vector<node> >m; 14 int dis[1005]; 15 int path[1005]; 16 bool vis[1005]; 17 int cnt[1005]; 18 int n, p, k; 19 const int INF = 0x7fffffff; 20 bool flag = true; 21 bool SPFA(int src) 22 { 23 memset(vis, 0, sizeof(vis)); 24 memset(cnt, 0, sizeof(cnt)); 25 for (int i = 1; i <= n; i++) 26 { 27 dis[i] = INF; 28 path[i] = src; 29 } 30 queue<int>q; 31 q.push(src); 32 dis[src] = 0, vis[src] = true; 33 cnt[src]++; 34 while (!q.empty()) 35 { 36 int v = q.front(); 37 q.pop(); 38 vis[v] = false; 39 int sz = m[v].size(); 40 for (int i = 0; i < sz; i++) 41 { 42 int u = m[v][i].to; 43 if (dis[v] + m[v][i].weight < dis[u]) 44 { 45 dis[u] = dis[v] + m[v][i].weight; 46 path[u] = v; 47 if (!vis[u]) 48 { 49 q.push(u); 50 vis[u] = true; 51 cnt[u]++; 52 if (cnt[u] > n) return false; 53 } 54 } 55 } 56 } 57 return true; 58 } 59 void Dij(int src) 60 { 61 memset(dis, -1, sizeof(dis)); 62 memset(vis, 0, sizeof(vis)); 63 memset(path, 0, sizeof(path)); 64 int sz = m[src].size(); 65 for (int i = 0; i < sz; i++) dis[m[src][i].to] = m[src][i].weight,path[m[src][i].to]=src; 66 for (int i = 1; i <= n; i++) if (dis[i] == -1) dis[i] = INF; 67 vis[src] = true, dis[src] = 0; 68 for (int i = 1; i <= n - 1; i++) 69 { 70 int u = src, min = INF; 71 for (int i = 1; i <= n; i++) 72 { 73 if (!vis[i] && dis[i] < min) u = i, min = dis[i]; 74 } 75 vis[u] = true; 76 sz = m[u].size(); 77 for (int i = 0; i < sz; i++) 78 { 79 int v = m[u][i].to; 80 if (!vis[v] && dis[u] + m[u][i].weight < dis[v]) 81 { 82 dis[v] = dis[u] + m[u][i].weight; 83 path[v] = u; 84 } 85 } 86 } 87 } 88 bool Judge(int mid) 89 { 90 for (int i = 1; i <= n; i++) 91 { 92 int sz = m[i].size(); 93 for (int j = 0; j < sz; j++) 94 { 95 if (m[i][j].length > mid) m[i][j].weight = 1; 96 else m[i][j].weight = 0; 97 } 98 } 99 //SPFA(1); 100 Dij(1); 101 if (dis[n] == INF) flag = false; 102 if (dis[n] <= k) return true; 103 else return false; 104 } 105 int main() 106 { 107 while (~scanf("%d%d%d", &n, &p, &k)) 108 { 109 m.clear(); 110 for (int i = 0; i <= n; i++) m.push_back(vector<node>()); 111 int L = 0, R = 0; 112 for (int i = 1; i <= p; i++) 113 { 114 int v, u, l; 115 scanf("%d%d%d", &v, &u, &l); 116 m[v].push_back(node(u, l)); 117 m[u].push_back(node(v, l)); 118 if (l > R) R = l; 119 } 120 flag = true; 121 if (Judge(0)) 122 { 123 printf("0\n"); 124 } 125 else if (!flag) 126 { 127 printf("-1\n"); 128 } 129 else 130 { 131 while (L <= R) 132 { 133 int mid = (L + R) / 2; 134 if (Judge(mid)) R = mid - 1; 135 else L = mid + 1; 136 } 137 printf("%d\n", L); 138 } 139 } 140 return 0; 141 }
View Code
6、UVA 1555 - Garland(推公式,贪心,二分搜索)
题意:有一个电线,给出最左边的电灯挂的高度,第i盏灯的高度为Hi = (H i-1 + H i+1)/2 - 1,共要挂n盏灯,并且高度不能低于地面。求最右边那盏灯的最低高度。
思路:Hi = (H i-1 + H i+1)/2 - 1转换为Hi=2*H(i-1)+2-H(i-2)。二分第二盏灯的高度,如果没有灯的高度低于地面,则看看能不能再降低,否则只能增大。
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 int n; 5 double A, B; 6 bool Judge(double x) 7 {//Hi=2*H(i-1)+2-H(i-2) 8 double h1 = A, h2 = x,h3; 9 for (int i = 3; i <= n; i++) 10 { 11 h3 = 2 * h2 + 2 - h1; 12 if (h3 < 0) return false; 13 h1 = h2, h2 = h3; 14 } 15 B = h3; 16 return true; 17 } 18 int main() 19 { 20 while (~scanf("%d%lf", &n, &A)) 21 { 22 double L = 0, R = A; 23 while (R - L >= 1e-6) 24 { 25 double mid = (R + L) / 2; 26 if (Judge(mid)) R = mid; 27 else L = mid; 28 } 29 printf("%.2lf\n", B); 30 } 31 return 0; 32 }
View Code
转载于:https://www.cnblogs.com/ivan-count/p/7228957.html
二分专题(不定期更新)相关推荐
- 搜索专题(不定期更新)
1.POJ 2386 Lake Counting 题意:给出一块区域,询问有多少个湖泊? 思路:DFS,对于'W',深搜一次,并标记已访问.之后每次对未访问的'W'做一次深搜. 1 #include ...
- Oracle OCP 11g 常见单词(不定期更新)
Oracle OCP 11g 常见单词(不定期更新) 数据库常见单词,不定期更新至考完ocp证(初步想法),现已收集807个单词: 最后一次更新时间为20180301. 1, ACCUMULATED ...
- 【代码总结-不定期更新】
[代码总结-不定期更新] 1 packagecom.runyi.share.service.information.commons.exceptions;2 3 importcom.runyi.ryp ...
- Android实用代码(不定期更新)
Android实用代码七段(一) 一抹火焰 整理(不定期更新) 前言 这里积累了一些不常见确又很实用的代码,每收集7条更新一次,希望能对大家有用. 声明: 欢迎转载,但请保留文章原始出处:) 博客园 ...
- 【☀️不定期更新了⛅】感谢知识输出的正反馈
不定期更新 最近沉迷写博,不能自拔.感谢知识输出的正反馈,又对知识学习燃起了激情.然而还是艰难地决定减少博客的时间投入,本地的技术总结markdown还是会继续写,博客可能不会每周定时发,以后可能就是 ...
- [刷题记录] luogu网络流24题 及 网络流心得体会 及 经典模型不定期更新
文章目录 信息汇总表格 飞行员配对方案问题 分配问题 运输问题 数字梯形问题 最小路径覆盖问题 魔术球问题 圆桌问题 试题库问题 深海机器人问题 航空路线问题 火星探险问题 太空飞行计划问题 方格取数 ...
- React性能优化记录(不定期更新)
React性能优化记录(不定期更新) 1. 使用PureComponent代替Component 在新建组件的时候需要继承Component会用到以下代码 import React,{Componen ...
- 区块链矿池(pool)汇总(不定期更新,欢迎评论区留言)
文章目录 辅助类网站 大型综合类矿池 Bitcoin/Litcoin/zcash Monero 不定期更新 辅助类网站 矿池算例排行:https://miningpoolstats.stream/bi ...
- Liunx上训练模型的常见情况(不定期更新)
这篇博客用来记录一些Linux上后台训练机器学习模型的时候可能用到的简短的代码(不定期更新) 目录: 后台执行python训练脚本 查看训练时占用的资源 中途停止模型的训练 1.后台执行python训 ...
- net core 小坑杂记之配置文件读取(不定期更新)
其实很早就想写了,原想等积累差不多了再写的,但是发现遇到一个当时记下效果会比较好,所以就不定期更新这个系列了,后面获取会整个整理一下. 此篇记载net core入门时踩的一些坑,网上教程太少了,也不规 ...
最新文章
- xilinx FIFO
- Skype for business混合部署系列之二自定义拓扑信息
- Spring面试五连问,这怎么顶啊
- python输出日期的模版_python按日期区间生成markdown日记模板
- 【Visual Studio 扩展工具】使用 ComponentOne迷你图控件,进行可视化数据趋势分析...
- Atitit 实现java的linq 以及与stream api的比较
- Android中的Dialog
- 关于pipelineDB调用GetLocalStreamReaders的BUG
- jre放到Tomcat目录并指定使用此jre的方法
- python计算一定期间的涨幅_python数据分析与挖掘(十一)--- ndarray运算
- Windows上SVN服务器搭建【转】
- win 10 系统怎么显示隐藏文件
- eclipse中如何远程java debug配置
- Ajax Session Timeout处理
- 基于python的图书管理系统设计与实现论文_图书馆管理系统的设计与实现毕业论文...
- 紫色范冰冰WIN7主题包
- Python内置函数一览表
- python 读写pcd
- android 史上最简单behavior,安卓behavior详解1--系统behavior的简单应用
- 【数据结构与算法】栈与队列【C语言版】
热门文章
- 斯坦福大学自然语言处理第二课“文本处理基础(Basic Text Processing)”
- Reason of Random Initialization - Neural Networks
- 数字值太大,plsql显示不全的设置
- python必须知道的三个概念_关于python编码,你真的明白了吗
- java.util.function包下的四大Function
- 原生php phpmailer 发送邮件 email
- Web jsp开发学习——Servlet提交表单时用法
- SSM+Jedis初体验
- BZOJ——T 1612: [Usaco2008 Jan]Cow Contest奶牛的比赛
- 讲解浏览器 三次握手四次挥手。