Codeforces 1016C Vasya And The Mushrooms

Radiumm發表於2018-08-30

題目連結: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;
}

 

相關文章