2020 ICPC Yinchuan

B. The Great Wall

显然我们可以很快的思考出来n3的做法
直接dp[i][j]表示前i个数分成j段的max 然后我们转移配合st表
dp[i][j]=max(dp[i][j],dp[k][j-1]+query_max(k+1,i)-query_min(k+1,i));
我们思考优化枚举
其实我们发现 我们只用维护一个最大值 和 最小值 即可
这样我们可以直接加一维保存最大值最小值的信息
dp[i][j][0/1/2/3]表示的是前i个分为了j组并且在第j组我们0是没有选出最大最小值
1表示我们确定了最大值 2表示我们确立了最小值 3表示我们两个都确定了
最后转移有些复杂 要做到不重不漏还是有点麻烦的

int dp[2][N][4],a[N];
void solve(){
    int n;cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    memset(dp,-0x3f,sizeof dp);
    dp[0][0][3]=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=i;j++){
            dp[i&1][j][0]=dp[i&1^1][j-1][3];
            dp[i&1][j][1]=dp[i&1^1][j-1][3]+a[i];
            dp[i&1][j][2]=dp[i&1^1][j-1][3]-a[i];
            dp[i&1][j][3]=dp[i&1^1][j-1][3];
            dp[i&1][j][0]=max(dp[i&1^1][j][0],dp[i&1][j][0]);
            dp[i&1][j][1]=max({dp[i&1^1][j][1],
                               dp[i&1^1][j][0]+a[i],dp[i&1][j][1]});
            dp[i&1][j][2]=max({dp[i&1^1][j][2],
                               dp[i&1][j][2],dp[i&1^1][j][0]-a[i]});
            dp[i&1][j][3]=max({dp[i&1^1][j][3],dp[i&1][j][3],
                             dp[i&1^1][j][1]-a[i],dp[i&1^1][j][2]+a[i]});
        }
    }
    for(int i=1;i<=n;i++)
        cout<<max(dp[n&1^1][i][3],dp[n&1][i][3])<<endl;
}
posted @ 2022-12-13 01:24  ycllz  阅读(20)  评论(0)    收藏  举报