Atcoder Beginner Contest 236 E Average and Median
E. Average and Median
题目大意
给定一个数组,从中选出一些数字,要求俩俩相邻的数中必选一个,最大化平均值和中位数。
中位数的定义为第小的数。
解题思路
刚开始想着各种贪心DP都觉得不对,直接整平均数不一定有最优子结构。事后发现可以二分答案判断。
就是二分平均数a
,如果对于选出来的数有 ,那么这个平均数就可以达到。
而判断能否选出这些数就是个简单dp,令,记表示第 个数选或不选的最大值,,最后看是否大于等于0即可。
中位数的话也一样,即如果有一半的数小于等于中位数。即令,同样用上述 ,最后看 是否大于0即可。
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; const double eps = 1e-5; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n; cin >> n; vector<int> qwq; LL sum = 0; for(int i = 1; i <= n; ++ i){ LL x; cin >> x; qwq.push_back(x); sum += x; } double l = 0, r = 1e9 + 7; auto check = [qwq](double x){ vector<vector<double>> dp(qwq.size(), vector<double>(2, 0)); dp[0][1] = qwq[0] - x; for(int i = 1; i < qwq.size(); ++ i){ dp[i][0] = dp[i - 1][1]; dp[i][1] = max(dp[i - 1][0], dp[i - 1][1]) + qwq[i] - x; } return dp.back()[0] >= 0 || dp.back()[1] >= 0; }; while(l + eps < r){ double mid = (l + r) / 2; if (check(mid)) l = mid; else r = mid; } cout << fixed << setprecision(8) << l << endl; auto check2 = [qwq](int x){ vector<vector<int>> dp(qwq.size(), vector<int>(2, 0)); dp[0][1] = (qwq[0] >= x) * 2 - 1; for(int i = 1; i < qwq.size(); ++ i){ dp[i][0] = dp[i - 1][1]; dp[i][1] = max(dp[i - 1][0], dp[i - 1][1]) + (qwq[i] >= x) * 2 - 1; } return dp.back()[0] > 0 || dp.back()[1] > 0; }; int ll = 0, rr = 1e9 + 7; while(ll + 1 < rr){ int mid = (ll + rr) >> 1; if (check2(mid)) ll = mid; else rr = mid; } cout << ll << endl; return 0; }
本文作者:~Lanly~
本文链接:https://www.cnblogs.com/Lanly/p/15850248.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
标签:
,
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步