《算法竞赛进阶指南》0.4二分

102. 最佳牛围栏

农夫约翰的农场由N块田地组成,每块地里都有一定数量的牛,其数量不会少于1头,也不会超过2000头。

约翰希望用围栏将一部分连续的田地围起来,并使得围起来的区域内每块地包含的牛的数量的平均值达到最大。

围起区域内至少需要包含 F块地,其中 F会在输入中给出。

在给定条件下,计算围起区域内每块地包含的牛的数量的平均值可能的最大值是多少。

输入格式
第一行输入整数 N和 F,数据间用空格隔开。

接下来 N行,每行输出一个整数,第i+1行输出的整数代表,第i片区域内包含的牛的数目。

输出格式
输出一个整数,表示围起区域内每块地包含的牛的数量的平均值可能的最大值乘以1000得到的数值。

数据范围
1≤N≤100000
1≤F≤N

输入样例:
10 6
6
4
2
10
3
8
5
9
4
1

输出样例:
6500

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

int n, m;
int cows[N];
double sum[N];

bool check(double avg)
{
    for(int i = 1; i <= n; i++) sum[i] = sum[i - 1] + cows[i] - avg;

    double minv = 0;
    for(int i = 0, j = m; j <= n; j++, i++)
    {
        minv = min(minv, sum[i]);
        if(sum[j] >= minv) return true;
    }
    return false;
}

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> cows[i];
    double l = 0, r = 2000;
    while(r - l > 1e-5) //保留3位小数 保留k位小数,取eps = -10^-(k+2)
    //***这里是r - l,右减左
    {
        double mid = (l + r) / 2;
        if(check(mid)) l = mid; // 这里l r 都可以,把小的干掉就行
        else r = mid;
    }
    printf("%d\n", (int)(r * 1000));

    return 0;
}

113. 特殊排序

有N个元素,编号1.2..N,每一对元素之间的大小关系是确定的,关系不具有传递性。

也就是说,元素的大小关系是N个点与N*(N-1)/2条有向边构成的任意有向图。

然而,这是一道交互式试题,这些关系不能一次性得知,你必须通过不超过10000次提问来获取信息,每次提问只能了解某两个元素之间的关系。

现在请你把这N个元素排成一行,使得每个元素都小于右边与它相邻的元素。

你可以通过我们预设的bool函数compare来获得两个元素之间的大小关系。

例如,编号为a和b的两个元素,如果元素a小于元素b,则compare(a,b)返回true,否则返回false。

将N个元素排好序后,把他们的编号以数组的形式输出,如果答案不唯一,则输出任意一个均可。

数据范围
1≤N≤1000

输入样例
[[0, 1, 0], [0, 0, 0], [1, 1, 0]]

输出样例
[3, 1, 2]

注意:不存在两个元素大小相等的情况。

// Forward declaration of compare API.
// bool compare(int a, int b);
// return bool means whether a is less than b.

class Solution {
public:
    vector<int> specialSort(int N) {
        vector<int> res;
        res.push_back(1);
        for(int i = 2; i <= N; i++)
        {
            int l = 0, r = res.size() - 1;
            while(l < r)
            {
                int mid = l + r + 1 >> 1;
                if(compare(res[mid], i)) l = mid; // res[mid] < i, 不在左半边里
                else r = mid - 1;
            }
            res.push_back(i);
            for(int j = res.size() - 2; j > r; j --) swap(res[j], res[j + 1]);
            if(compare(i, res[r])) swap(res[r], res[r + 1]); //i < res[r]
        }
        return res;
    }
};

原文地址:https://www.cnblogs.com/wmxnlfd/p/10847657.html

时间: 2024-11-08 22:46:44

《算法竞赛进阶指南》0.4二分的相关文章

《算法竞赛进阶指南》学习总结 二分与三分

首先......我是一个很菜很菜的萌新,所以这篇文章写得很详细,有很多我自己的口水话方便我理解,请各位谨慎食用qwq 以前在网上找过很多介绍二分的博客,但都感觉对萌新不太友好,反正我当时连跳石头都没看懂,所以决定自己写一篇!其中有我的想法,也借鉴了书里的很多内容,感谢lyd. 二分答案,顾名思义,就是对我们所需要的答案进行二分,对我们要求的值进行二分.二分的基础用法是在单调序列或者单调函数当中查找,当答案具有单调性,我们就可以采用二分来计算,当然还有三分,在后面我会详细讲到 整数集合上的二分 在

《算法竞赛进阶指南》学习总结 #include&lt;algorithm&gt;

今天下午大致学完了进阶指南中algorithm头文件下的内容,在这里进行一个总结.   reverse翻转   顾名思义,reverse进行的操作就是翻转原来的顺序,理解非常简单,故不赘述. 操作样例: #include<bits/stdc++.h> using namespace std; vector<int>a; int b[233]; int main() { int na,nb; //vector的实现 scanf("%d",&na); for

《算法竞赛进阶指南》0.8总结与练习(1)

116. 飞行员兄弟 "飞行员兄弟"这个游戏,需要玩家顺利的打开一个拥有16个把手的冰箱. 已知每个把手可以处于以下两种状态之一:打开或关闭. 只有当所有把手都打开时,冰箱才会打开. 把手可以表示为一个4х4的矩阵,您可以改变任何一个位置[i,j]上把手的状态. 但是,这也会使得第i行和第j列上的所有把手的状态也随着改变. 请你求出打开冰箱所需的切换把手的次数最小值是多少. 输入格式 输入一共包含四行,每行包含四个把手的初始状态. 符号"+"表示把手处于闭合状态,而

《算法竞赛进阶指南》0.6倍增

109. 天才ACM 给定一个整数 M,对于任意一个整数集合 S,定义"校验值"如下: 从集合 S中取出 M 对数(即 2?M 个数,不能重复使用集合中的数,如果 S 中的整数不够 M 对,则取到不能取为止),使得"每对数的差的平方"之和最大,这个最大值就称为集合 S的"校验值". 现在给定一个长度为 N的数列 A 以及一个整数 T. 我们要把 A分成若干段,使得每一段的"校验值"都不超过 T. 求最少需要分成几段. 输入格式

算法竞赛进阶指南做题记录

基本算法 递归与递推 费解的开关 Strange Towers of Hanoi Sumdiv Fractal Streets 前缀和与差分 激光炸弹 IncDec Sequence Tallest Cow 二分 Best Cow Fences 排序 Cinema 货舱选址 七夕祭 Running Median 第K大数 Ultra-QuickSort 奇数码问题 原文地址:https://www.cnblogs.com/Maktub-blog/p/11009723.html

算法竞赛进阶指南 走廊泼水节

原题链接 题目描述 给定一棵N个节点的树,要求增加若干条边,把这棵树扩充为完全图,并满足图的唯一最小生成树仍然是这棵树. 求增加的边的权值总和最小是多少. 输入格式 第一行包含整数t,表示共有t组测试数据. 对于每组测试数据,第一行包含整数N. 接下来N-1行,每行三个整数X,Y,Z,表示X节点与Y节点之间存在一条边,长度为Z. 输出格式 每组数据输出一个整数,表示权值总和最小值. 每个结果占一行. 数据范围 \(N \le 6000,Z \le 100\) 输入样例: 2 3 1 2 2 1

bzoj 1787 &amp;&amp; bzoj 1832: [Ahoi2008]Meet 紧急集合(倍增LCA)算法竞赛进阶指南

题目描述 原题连接 Y岛风景美丽宜人,气候温和,物产丰富. Y岛上有N个城市(编号\(1,2,-,N\)),有\(N-1\)条城市间的道路连接着它们. 每一条道路都连接某两个城市. 幸运的是,小可可通过这些道路可以走遍Y岛的所有城市. 神奇的是,乘车经过每条道路所需要的费用都是一样的. 小可可,小卡卡和小YY经常想聚会,每次聚会,他们都会选择一个城市,使得3个人到达这个城市的总费用最小. 由于他们计划中还会有很多次聚会,每次都选择一个地点是很烦人的事情,所以他们决定把这件事情交给你来完成. 他们

《算法竞赛进阶指南》打卡活动 #0x00 基本算法

101. 最高的牛 题目链接:https://www.acwing.com/problem/content/103/ 作为一个银牌水平的主演数据结构的演员来说,这题现在发现非常好想,每个牛分配一个优先度.我搞一个区间线段树,每次update中间一段使得他们的优先度整体下降到比两端中较小的优先度还要小.然后反过来按照优先度分配身高.哈哈!根本不需要什么算法.不过每次都不询问为什么要线段树呢?差分不香吗?当然不香,每次询问当前的优先度啊! const int MAXN = 10000; int re

【算法竞赛进阶指南】USACO07Tallest Cow

前缀和,利用左右端点操作代替对区间的操作,从而优化输入,最后进行一次前缀和的操作,求得结果,这道题里面有个很关键的问题,就是需要去重,本来我想用set,但貌似有点鬼畜,算了,利用map去重,还有pair类型(学一下) #include <iostream> #include <algorithm> #include <map> #include <utility> using namespace std; map<pair<int,int>