题目链接:http://codeforces.com/contest/1016/problem/C
题意:从左上角格子开始走,每次走一个临近的格子,速率为1,走过的格子取走所有的蘑菇,每个格子上的蘑菇有一个增长速率,问获得的最大的增长速率是多少
分析:dp。除了样例中给的两种走法,还有可能是两种走法的结合。预处理出来每次折线走法的每一个格子获得的速率值,绕圈走法左边的列相当于它右边的一列加上一个后缀和(因为走过一格后面的格子相当于时间多了1,加上增长速率和即可),为了保证获得的速率值最大,只能是先折线走再绕圈走,绕圈走可能是从上到下或者从下到上,类似处理即可,注意long long 。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 10;
typedef long long ll;
ll a[maxn],b[maxn];
ll S1[maxn],S2[maxn],S3[maxn],S4[maxn],SS[maxn];
int n;
void init1()//走折线,从上往下走
{
for(int i = 1; i <= n; i++)
{
if(i % 2)
{
S1[i] = a[i] * (2 * i - 2);
S1[i] += S1[i - 1];
S2[i] = b[i] * (2 * i - 1);
S2[i] += S1[i];
}
else
{
S2[i] = b[i] * (2 * i - 2);
S2[i] += S2[i - 1];
S1[i] = a[i] * (2 * i - 1);
S1[i] += S2[i];
}
}
}
void init2()
{
ll ans = 0;
for(int i = n; i >= 1; i--)
{
ans += a[i] + b[i];
SS[n - i + 1] = ans;
}
}
void init3()//前面的由后面的转移过来,每次增加一个后缀和
{
for(int i = n,l = 0; i >= 1; i--,l++)//从上到下
{
S3[i] = S3[i + 1] + SS[l] + b[i] * (2 * l + 1);
}
for(int i = n,l = 0; i >= 1; i--,l++)//从下到上
{
S4[i] = S4[i + 1] + SS[l] + a[i] * (2 * l + 1);
}
}
int main()
{
cin>>n;
for(int i = 1; i <= n; i++)
{
cin>>a[i];
}
for(int i = 1; i <= n; i++)
{
cin>>b[i];
}
init1();
init2();
init3();
ll ans = 0;
ans = S3[1];
for(int i = 1; i <= n; i++)
{
if(i % 2 == 0)
{
ans = max(ans,S1[i] + S3[i + 1] + (i * 2) * SS[n - i]);
}
else
{
ans = max(ans,S2[i] + S4[i + 1] + (i * 2) * SS[n - i]);
}
}
cout<<ans<<endl;
return 0;
}