2021西电校赛网络选拔赛 D.咕的头发问题 (dp)
Posted Accelerator
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021西电校赛网络选拔赛 D.咕的头发问题 (dp)相关的知识,希望对你有一定的参考价值。
-
题意:有\\(n\\)个数,可以使任意两个子数组(不重叠)的元素贡献*2,问你操作后整个数组的最大元素和是多少.
-
题解:假如我们只能操作的一次的话,这题完全可以转换为求最大子段和,即先求出所有元素和,然后再加上最大子段和即可,但是现在我们需要求出两个最大子段和,也就意味着在操作一次的基础上,可以使区间断开分成两个,可是这样dp方程并不好转移,但根据这个断开的思想,我们不难想到可以正序和倒序分别求出两个最大子段和,然后维护一下前缀最大和后缀最大,最后枚举断开的位置,在所有元素和的基础上再加上前缀和后缀即可.
-
代码:
#include <bits/stdc++.h> #define ll long long #define fi first #define se second #define pb push_back #define me memset #define rep(a,b,c) for(int a=b;a<=c;++a) #define per(a,b,c) for(int a=b;a>=c;--a) const int N = 1e6 + 10; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; using namespace std; typedef pair<int,int> PII; typedef pair<ll,ll> PLL; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} ll lcm(ll a,ll b) {return a/gcd(a,b)*b;} int n; ll a[N]; ll dp[N][2]; int main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); cin>>n; rep(i,1,n) cin>>a[i]; rep(i,1,n){ dp[i][0]=max(a[i],dp[i-1][0]+a[i]); } per(i,n,1){ dp[i][1]=max(a[i],dp[i+1][1]+a[i]); } rep(i,1,n){ dp[i][0]=max(dp[i][0],dp[i-1][0]); } per(i,n,1){ dp[i][1]=max(dp[i][1],dp[i+1][1]); } ll sum=0; rep(i,1,n){ sum+=a[i]; } ll ans=-1e18; rep(i,1,n){ ans=max(ans,sum+dp[i-1][0]+dp[i][1]); } cout<<ans<<\'\\n\'; return 0; }
以上是关于2021西电校赛网络选拔赛 D.咕的头发问题 (dp)的主要内容,如果未能解决你的问题,请参考以下文章