AtCoder Beginner Contest 236 E - Average and Median
阿新 • • 發佈:2022-01-25
E - Average and Median
E - Average and Median (atcoder.jp)
題目大意:給你n個數,在其中選數字,要求每相鄰的兩個數至少需要選其中一個,求出最大的平均數和中位數,此處的中位數定義為第\(\lceil \frac{n}{2} \rceil\)小的數字
思路:
首先,求大於k的平均數可以轉化為求m,且m滿足每一項減m後,各項之和≥0,而最大的m即為我們所求的最大的平均數k。求該題目中的最大中位數k可以轉化為求m,且m滿足比m大的數字個數大於比m小的數字個數,而最大的m一定能保證是中位數,同時也是最大的中位數k
而求m的過程可以用二分答案 + DP
設f[i] 表示選第i項時,前i項中所有被選的項的最大和
我們二分列舉求平均數是需要用到實數域二分,可以用for迴圈也可以用while(r - l > eps)
然後把每一項減去mid,二分的判斷條件是此時最大和是否大於等於0
二分列舉求中位數,需要判斷序列每一項,如果該項大於等於mid,則為1,否則為-1
二分的判斷條件也是此時最大和是否大於等於0
程式碼示例:
//#pragma comment(linker, "/STACK:10240000000000,10240000000000") //#pragma GCC optimize(2) #include <bits/stdc++.h> using namespace std; #define rep(i,a,b) for (int i=(a);i<=(b);++i) #define endl '\n' #define IOS ios::sync_with_stdio(0); cin.tie(0); #define lowbit(x) x & (-x) #define clr(x) memset(x, 0, sizeof(x)); #define fi first #define se second typedef vector<int> vii; typedef vector<long long> vll; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; typedef pair<ll, ll> pll; const pii moves[] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; ll ksm(ll a, ll b, ll p) {if (b == 0) return 1; ll ns = ksm(a, b >> 1, p); ns = ns * ns % p; if (b & 1) ns = ns * a % p; return ns;} inline int read() { int x = 0, w = 0; char ch = getchar(); while(ch < '0' || ch > '9'){w |= ch == '-';ch = getchar();} while(ch >= '0' && ch <= '9'){x = (x << 3) + (x << 1) + ch - '0';ch = getchar();} return w ? -x : x; } const int MAXN = 0x7fffffff; int main () { //IOS; int n; cin >> n; vii a(n); for (int i = 0; i < n; i ++) cin >> a[i]; { double l = 0, r = 1e9; double mid; for(int i = 1; i <= 1000; i ++) { mid = (l + r) / 2; vector<double> f(n + 5, 0); f[0] = a[0] - mid; for(int i = 1; i < n; i ++) { if(i < 2) f[i] = max(f[i], f[i - 1]) + a[i] - mid; if(i > 1) f[i] = max(f[i - 1], f[i - 2]) + a[i] - mid; } if(max(f[n - 1], f[n - 2]) >= 0) l = mid; else r = mid; } cout << fixed << setprecision(10) << l << endl; } { int l = 0, r = 1e9; while(l < r) { double mid = (l + r + 1) / 2; vii f(n + 5, -1e9); for (int i = 0; i < n; i ++) { if(i < 2) f[i] = 0; if(i > 0) f[i] = max(f[i], f[i - 1]); if(i > 1) f[i] = max(f[i], f[i - 2]); f[i] += a[i] >= mid ? 1 : -1; } if(max(f[n - 2], f[n - 1]) > 0) l = mid; else r = mid - 1; } cout << l << endl; } return 0; } /* */