D. Maximum Sum on Even Positions(动态规划,思维)
D. Maximum Sum on Even Positions
原题链接:传送门
题目大意
给定一个数组,你可以交换数组中的任意一个子数组,要求执行一次交换后使得整个数组的偶数位置的元素和达到最大。
分析
此题的关键还是在于将新的问题转化为原有的问题模型
第二次拿到这道题依旧使无从下手,如果来了解过最大连续子段和的问题的得话那么应该会对这个问题有一些启发。通过分析首先我们应该可以知道交换的子数组一定是偶数长度,否则将没有意义。
那么我们可以将该问题转化一下:
假设对于1 7 3 4 这个序列
如果我们交换了 1 7那么可以收获的权值为7 - 1 = 6
如果我们继续扩大长度交换3 4 那么此时的可以收获的权值为 6 + 4 - 3 = 7
对于此我们可以将其转化为求解数组b的最大连续子数组和的问题
b[i] = (a[i] - a[i + 1]) / b[i] = a[i - 1] - a[i]
AC 代码
AC code
void slove()
{
int n;cin >> n;
ll res = 0;
vector<ll> b , c;
for(int i = 0;i < n ;i ++)
{
cin >> a[i];
if(i % 2 == 0)res += a[i];
}
for(int i = 1;i < n ;i += 2)b.PB(a[i] - a[i - 1]);
for(int i = 2;i < n ;i += 2)c.PB(a[i - 1] - a[i]);
ll sum = -1e9, ans = 0;
for(int i = 0;i < b.size() ;i ++)
{
if(sum > 0)sum += b[i];
else sum = b[i];
ans = max(ans , sum);
}
sum = -1e9;ans = max(ans , sum);
for(int i = 0;i < c.size() ;i ++)
{
if(sum > 0)sum += c[i];
else sum = c[i];
ans = max(ans , sum);
}
cout << ans + res << endl;
}
标程/优秀代码
void slove()
{
int n;cin >> n;
vector<int> a(n + 1);
ll ans = 0 ,sum1 = 0,sum2 = 0,mx = 0;
REP(i , 1 , n)
{
cin >> a[i];
if(i % 2 == 1)ans += a[i];
}
for(int i = 2;i <= n;i += 2)
{
sum1 = max((ll)0 , a[i] - a[i-1] + sum1);
mx = max(mx , sum1);
}
for(int i = 3;i <= n;i +=2)
{
sum2 = max((ll)0 , a[i-1] - a[i] + sum2);
mx = max(mx , sum2);
}
cout << ans + mx << endl;
}