1. 程式人生 > 其它 >AtCoder Beginner Contest 236 E - Average and Median

AtCoder Beginner Contest 236 E - Average and Median

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;
}	
/*

*/