F - Select Half
题意:
有 n 个数,求取 ⌊⌋ 个两两不相邻的数的最大和。
数据范围:
2 ≤ N ≤ 2 ×
∣Ai∣ ≤
思路:
状态表示:dp[i] 表示前 i 个数中取 ⌊ ⌋ 个数的最大和。
状态计算:以 i 的奇偶性划分:
1.如果 i 是奇数。选 a[i] 时,等价于从前 i-2 个数中选,即 dp[i] = dp[i-2] + a[i];不选 a[i] 时,等价于从前 i-1 个数中选,即 dp[i] = dp[i-1].
2.如果 i 是偶数。选 a[i] 时,同上,即 dp[i] = dp[i-2] + a[i];不选 a[i] 时,因为 i 为偶数,要在不选第 i 个数的情况下选够 i/2 个数,就只能从开头 a1 开始选,每隔一个数就选上。即dp[i] = a[i] + a[3] + …… + a[i-1]。
我们用数组 pre_sum[i] 表示对数组a取前 i 个数的奇数位的数的和。所以:
i 为奇数:dp[i] = max(dp[i-2] + a[i], dp[i-1]);
i 为偶数:dp[i] = max(dp[i-2] + a[i], pre_sum[i-1])
Code:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define x first
#define y second
#define int long long
const int N = 200010, INF = 0x3f3f3f3f, mod = 1e9 + 7;
typedef pair<int, int>PII;
int n;
int a[N];
int dp[N];
int pre_sum[N];
void solve()
{
cin >> n;
for (int i = 1; i <= n; i++)cin >> a[i];
for (int i = 1; i <= n; i += 2)
pre_sum[i] = pre_sum[i - 2] + a[i];
for (int i = 2; i <= n; i++)
{
if (i & 1) //如果i是奇数
dp[i] = max(dp[i - 1], dp[i - 2] + a[i]);
else //如果i是偶数
dp[i] = max(pre_sum[i - 1], dp[i - 2] + a[i]);
}
cout << dp[n] << endl;
}
signed main()
{
int t = 1;
//cin >> t;
while (t--)
{
solve();
}
return 0;
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
吐槽:这次F题代码很短,重点就是思路,可惜想不到。