codeforces 343C Read Time 二分 + 贪心

http://codeforces.com/problemset/problem/343/C

题意:

有一些磁头,给出了起始的位置,给出了一些磁盘中需要访问的地点。求这些磁头移动的最小的次数。

思路:

二分找出满足要求的最小的时间,对于当前尝试的时间进行贪心判断是否可用。对于贪心,因为每一个磁头都需要读到还没有人读过的最左边的地方。如果这个都不能满足,那么这个时间是不可以的。

在这基础上,对于同样的这么多时间,尽可能的让这个磁头读到能读到的最右边,这样就可以将还没有读过的地方尽可能的往右推。

如果这样最后能够将所有读取完,那么这个时间是可以的。

确定能读到的最右边(当然首先要保证读到还未读过的最左边,这是前提。),同样的时间,两种行走的方式,1)先向左走,后向右走。能向右走t?2?(h[i]?p[step])的距离。2)先向右走,后想左走。能向右走(t?(h[i]?p[step])/2的距离。选择一个最大的。

再更新尚未访问的最左边的位置。

总结:

类似最大化最小值,最小化最大值的题目做了有几道了,但是感觉还是没有什么感觉,经常就想不到,对于直接二分答案这种思想还会不够敏感吧。

总结一下这些最大化最小值等这类问题吧。

首先要寻找的这个答案是在一个确定的范围里,超过多少或小于多少就不能作为答案,题目往往要求的是这个答案的最大值,或者最小值, 就要最大化或者最小化这个答案。要找的这个就肯定是在边界附近,对于这题来说就是再小一点的时间就不可以满足了。

对于这样就要想到二分找答案的方法,因为这个就是一个连续单调的,在一个点将满足与不满足的分开。

这样的题还有一个地方就是需要构造出一个判断当前找的这个答案是否满足条件的方法,需要快速的判断这个是否可以满足。这题里面运用的就是贪心。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 100009
typedef long long ll;
int n,m;
ll h[M],p[M];
bool judge(ll t)
{
    int step = 0; //表示最左边未读取过的点
    for(int i = 0;i < n;i++)
    {
        if(step >= m) break;
        if(h[i] - p[step] > t) return false;  //走不到最左边
        ll s = h[i];
        if(h[i] < p[step]) //当前磁头已经在要读的最左的地方的右边。
            s = h[i] + t;
        else
        {
            s = max(s,h[i]+t-2*(h[i]-p[step])); //先左走后右走
            s = max(s,h[i]+(t-(h[i]-p[step]))/2); //先右走后左走
        }
        while(step < m && p[step] <= s) step++; //更新最左边未读取的
    }
    if(step < m) return false;
    return true;
}
int main()
{
    while(scanf("%d %d",&n,&m) == 2)
    {
        for(int i = 0;i < n;i++)
            scanf("%I64d",&h[i]);
        for(int i = 0;i < m;i++)
            scanf("%I64d",&p[i]);
        ll low = -1,high = -1;
        if(h[0] < p[0]) //确定high的上限
            high = p[m-1] - h[0];
        else
        {
            high = max((h[0]-p[0])*2+p[m-1]-h[0],(p[m-1]-h[0])*2+h[0]-p[0]);
        }
        while(high - low > 1) //找出最小值,边界的判定要小心
        {
            ll mid = (high+low) >> 1;
            if(judge(mid)) high = mid; //满足缩小上限
            else low = mid;
        }
        printf("%I64d\n",high);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-09-29 16:47:36

codeforces 343C Read Time 二分 + 贪心的相关文章

Codeforces 1132D - Stressful Training - [二分+贪心+优先队列]

题目链接:https://codeforces.com/contest/1132/problem/D 题意: 有 $n$ 个学生,他们的电脑有初始电量 $a[1 \sim n]$,他们的电脑每分钟会耗电 $b[1 \sim n]$,现在有一场比赛持续 $k$ 分钟. 要你买一个充电器,使得每个学生的电脑在比赛期间的任何时候的电量都不会低于 $0$(可以等于 $0$),你要求出这个充电器每分钟充电量最少是多少. 题解: 看到这种题目,应当条件反射想到二分. 假设我们现在知道充电器每分钟的充电量是

Codeforces 830A. Office Keys (背包dp+贪心) / (二分+贪心)

题目链接: http://codeforces.com/problemset/problem/830/A 题意: n个人,k个钥匙(n<=k),p表示这些人要到达的位置 给出n个人的位置以及钥匙的位置,问花时间最多的那个人用时最少是多少?? 思路: 二分+贪心: 二分最少时间,需要对a,b位置数组排序,我们check函数只需要从左到右一个一个找过去,因为如果选后边的点,可能会使结果更差,假如当前这个人选后面的点,那可能会选中后面的人可以选的唯一的钥匙,不会使解更优. check(40)的时候答案

二分+贪心

上海邀请赛热身时候,C题是一个二分+贪心的题目.起初并不会,问了旁边的复旦大神.这几天无意发现VJ上一个专题.擦原来是一个经典类型. 二分+贪心 这类题目注意数据范围,1e8,1e9一般都是这样. 注意事项 二分法有很多写法,推荐用lf+1 < rf的写法.这个也符合计算机中数据存取的原则.对于浮点数,直接就循环100次,精度绝对够. 一般有两种类型,一种是询问最优,即数列中无重复.一种是多个即lower_bound ,upper_bound这类函数问题. 贪心使用,就是这个问题枚举答案可被验证

nyoj586||poj2456 二分+贪心

完全看不懂题意....百度搜搜才看懂题意  然后就参考代码了 和yougth的最大化()nyoj914差不多的方法 二分+贪心 #include <stdio.h> #include <algorithm> using namespace std; int c,a[100005],n; bool judge(int k) { int p=a[0],cnt=1;//也就这里注意点 从1开始 自己想想为啥 for(int i=1;i<n;i++) { if(a[i]-p>=

HDU 4004 The Frog&#39;s Games 二分 贪心

戳这里:HDU 4004 //思路:二分经典入门题...贪心判方案是否可行 1 #include "bits/stdc++.h" 2 using namespace std; 3 int L, n, m; 4 int pos[500010], dis[500010]; 5 6 bool Cant(int Dis_Jump) 7 { 8 int i, Dis_Sum = 0, Count = 0; 9 for(i = 1; i <= n + 1; ++i) { 10 if(dis[

Codeforces 442B Andrey and Problem(贪心)

题目链接:Codeforces 442B Andrey and Problem 题目大意:Andrey有一个问题,想要朋友们为自己出一道题,现在他有n个朋友,每个朋友想出题目的概率为pi,但是他可以同时向多个人寻求帮助,不过他只能要一道题,也就是如果他向两个人寻求帮助,如果两个人都成功出题,也是不可以的. 解题思路:贪心,从概率最大的人开始考虑,如果询问他使得概率变大,则要询问. #include <cstdio> #include <cstring> #include <a

贪心(bnuoj49103+二分+贪心)

贪心 小明喜欢养小鸡,小鸡喜欢吃小米.小明很贪心,希望养s只不同种类的小鸡,小鸡也很贪心,每天除了吃固定的ai粒小米外,还想多吃bi*s粒小米. 小明每天有M(0<=M<=10^9)粒小米可以喂小鸡,小鸡共有N(0<=N<=1000)种.问小明最多可以养多少只小鸡? Input 多组数据,请读到文件尾 第一行,整数N,M,以空格分隔,之后两行,第一行为N个整数ai,第二行为N个整数bi. ai.bi都在int范围内 Output 一行一个整数,s. Sample Input 2 4

poj1505Copying Books 二分+贪心详细总结

前两天花了时间理解了nyoj的586疯牛和nyoj619青蛙过河,满以为自己能重新写出这道题...谁知道..... 题意:有m本书,k个人来抄,每本书有一个书本页数:求使得k个人抄完的最大页数最小,并且每个人都至少要抄一本,然后输出抄书的方案 分析: 这里又涉及到前面nyoj的586疯牛和nyoj619青蛙过河说过的最大值中的最小值,  用前面的例子去理解比较方便 1.我们应该先用二分+贪心算出一个最大页数的最小值--这里和前面的类似 在二分的过程中,我们对于当前考虑的值 x  划分人数的贪心过

【bzoj2097】[Usaco2010 Dec]Exercise 奶牛健美操 二分+贪心

题目描述 Farmer John为了保持奶牛们的健康,让可怜的奶牛们不停在牧场之间 的小路上奔跑.这些奶牛的路径集合可以被表示成一个点集和一些连接 两个顶点的双向路,使得每对点之间恰好有一条简单路径.简单的说来, 这些点的布局就是一棵树,且每条边等长,都为1. 对于给定的一个奶牛路径集合,精明的奶牛们会计算出任意点对路径的最大值, 我们称之为这个路径集合的直径.如果直径太大,奶牛们就会拒绝锻炼. Farmer John把每个点标记为1..V (2 <= V <= 100,000).为了获得更加