Vijos - [一本通 1.2 例 2]Best Cow Fences(二分)

题目链接https://vijos.org/d/ybttg/p/5c24bad1f41362c9e191275c
时间限制:1000 ms 内存限制:512 MiB

题目描述

原题来自:USACO 2003 Mar. Green

给定一个长度为 n n 的非负整数序列 A A ,求一个平均数最大的,长度不小于 L L 的子段。

输入格式

第一行用空格分隔的两个整数 n n L L
第二行为 n n 个用空格隔开的非负整数,表示 A i A_i

输出格式

输出一个整数,表示答案的 1000 1000 倍。不用四舍五入,直接输出。

样例数据

样例输入

10 6
6 4 2 10 3 8 5 9 4 1

样例输出

6500

限制与提示

1 n 1 0 5 , 0 A i 2000 1 \leq n \leq 10^5, 0 \leq A_i \leq 2000

题解

题意:给定一个非负序列,求长度大于F的连续子序列的平均数最大。
思路:二分平均数mid,判断a中是否有长度大于L平均数大于等于mid,再进行调整二分区间。

假设有一个b数组,b[i]=a[i]-mid,当b[i]的区间和大于等于0的时候说明区间平均数大于等于mid。

用sum数组表示b数组前缀和,再求出长度大于等于L的所有区间中的最大区间和=前缀和-前面的最小前缀和(要保证区间长度大于L),判断和是否大于等于0(只要有一个就大于等于0就行)。

Accepted Code:

/* 
 * @Author: lzyws739307453 
 * @Language: C++ 
 */
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
const long long inf = 0x3f3f3f3f3f3f3f3f;
int n, m, a[MAXN];
long long sum[MAXN];
struct ios_in {
    inline char gc() {
        static char buf[MAXN], *l, *r;
        return (l == r) && (r = (l = buf) + fread(buf, 1, MAXN, stdin), l == r) ? EOF : *l++;
    }
    template <typename _Tp>
    inline ios_in & operator >> (_Tp &x) {
        static char ch, sgn;
        for (sgn = 0, ch = gc(); !isdigit(ch); ch = gc()) {
            if (!~ch) return *this;
            sgn |= ch == '-';
        }
        for (x = 0; isdigit(ch); ch = gc())
            x = (x << 1) + (x << 3) + (ch ^ '0');
        sgn && (x = -x);
        return *this;
    }
}Cin;
struct ios_out {
    template <typename _Tp>
    inline void operator << (_Tp &x) {
        char F[MAXN];
        _Tp tmp = x > 0 ? x : (putchar('-'), -x);
        int cnt = 0;
        while (tmp) {
            F[cnt++] = tmp % 10 + '0';
            tmp /= 10;
        }
        while (cnt) putchar(F[--cnt]);
    }
}Cout;
bool Check(int x) {
    long long min_ = inf;
    for (int i = 1; i <= n; i++)
        sum[i] = sum[i - 1] + a[i] - x;
    for (int i = m; i <= n; i++) {
        min_ = min(min_, sum[i - m]);
        if (sum[i] - min_ >= 0)
            return true;
    }
    return false;
}
int main() {
    int l = 0, r = 0;
    Cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        Cin >> a[i];
        a[i] *= 1000;
        r = max(r, a[i]);
    }
    while (l < r) {
        int mid = l + ((r - l + 1) >> 1);
        if (Check(mid))
            l = mid;
        else r = mid - 1;
    }
    Cout << l, putchar('\n');
    return 0;
}
发布了808 篇原创文章 · 获赞 331 · 访问量 244万+

猜你喜欢

转载自blog.csdn.net/lzyws739307453/article/details/101864362