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\n", ans); } } int main() { // int _; scanf("%d", &_); // while(_--) solve(); solve(); return 0; }
一步一步,永不停息