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

題目鏈接https://vijos.org/d/ybttg/p/5c24bad1f41362c9e191275c
時間限制:1000 ms 內存限制:512 MiB

題目描述

原題來自:USACO 2003 Mar. Green

給定一個長度爲nn的非負整數序列AA,求一個平均數最大的,長度不小於LL的子段。

輸入格式

第一行用空格分隔的兩個整數nnLL
第二行爲nn個用空格隔開的非負整數,表示AiA_i

輸出格式

輸出一個整數,表示答案的10001000倍。不用四捨五入,直接輸出。

樣例數據

樣例輸入

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

樣例輸出

6500

限制與提示

1n105,0Ai20001 \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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章