ZOJ 2091 Mean of Subsequence (思维 贪心)

题目:传送门

题意

Roy 和 PMH 在玩游戏,给定一个长度为 n 的序列,Roy 选子序列的起点,PMH 选子序列的长度,Roy 希望子序列的平均值尽可能大, PMH 希望子序列的平均值尽可能小。假设两人都足够聪明,问 Roy 能获得的最大的平均值是多少,保留6位小数。

思路

结论:对于任何 Roy 选定的起点,PMH 都会使得子序列的长度最大化。

证明:(反证法)

假设 Roy 选定的最优起点为 k,而 PMH 选的终点不是 n,而是 k ~ n 之间的某个数 t,那么就有 t ~ n 的平均值大于 k ~ t 的平均值,也就是说选 t 为起点,得到的平均值大于选 k 为起点时的平均值,与假设不符。

那么问题就简化为,求所有后缀的平均值的最大值。

#include <bits/stdc++.h>
#define LL long long
#define ULL unsigned long long
#define UI unsigned int
#define mem(i, j) memset(i, j, sizeof(i))
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
#define make make_pair
#define INF 0x3f3f3f3f
#define inf LLONG_MAX
#define PI acos(-1)
#define fir first
#define sec second
#define lb(x) ((x) & (-(x)))
#define dbg(x) cout<<#x<<" = "<<x<<endl;
using namespace std;

const int N = 1e6 + 5;

double a[N];

void solve() {

    int n;

    while(~scanf("%d", &n)) {

        rep(i, 1, n) scanf("%lf", &a[i]);

        double sum = 0;

        double ans = -1;

        dep(i, 1, n) {

            sum += a[i];

            double tmp = (double)(sum / (n - i + 1));

            if(tmp > ans) ans = tmp;

        }

        printf("%.6f
", ans);
    }

}

int main() {

//    int _; scanf("%d", &_);
//    while(_--) solve();

    solve();

    return 0;
}
原文地址:https://www.cnblogs.com/Willems/p/12882690.html