CF2021D Boss, Thirsty

原题链接

原来就是直接做啊。

\(s_{i,j}=\sum\limits_{k\leq j} a_{i,k}\),设 \(f_{i,x,y}\) 表示第 \(i\) 行选区间 \([x,y]\) 的最大答案,有转移:

\[f_{i,x,y}=s_{i,y}-s_{i,x-1}+\max(\max\limits_{x<l\leq y,r\geq l} f_{i-1,l,r},\max\limits_{x\leq r<y,l\leq r} f_{i-1,l,r}) \]

\(L_{i,l},R_{i,r}\) 分别表示 \(\max\limits_{r\geq l} f_{i,l,r},\max\limits_{l\leq r} f_{i,l,r}\),转移变为:

\[f_{i,x,y}=s_{i,y}-s_{i,x-1}+\max(\max\limits_{x<l\leq y} L_{i-1,l},\max\limits_{x\leq r<y} R_{i-1,r}) \]

考虑直接求 \(L_{i,x},R_{i,y}\)

\[L_{i,x}=\max\limits_{y\geq x} f_{i,x,y}=-s_{i,x-1}+\max(\max\limits_{l>x} (L_{i-1,l}+\max\limits_{y\geq l} s_{i,y}),\max\limits_{r\geq x} (R_{i-1,r}+\max\limits_{y>r} s_{i,y})) \]

\[R_{i,y}=\max\limits_{x\leq y} f_{i,x,y}=s_{i,y}+\max(\max\limits_{l\leq y} (L_{i-1,l}-\min\limits_{x<l} s_{i,x-1}),\max\limits_{r<y} (R_{i-1,r}-\min_{x\leq r} s_{i,x-1})) \]

计算四个括号里的东西即可,注意能否取等,这意味着一些计算的先后顺序。第一行要特殊处理。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<vector>
#define int long long
using namespace std;
typedef pair<int,int> P;
const int N=2e5+10,INF=1e18;
int T,n,m,s[N],l[N],r[N],a[N],b[N],c[N],d[N];
inline void work()
{
    cin>>n>>m;int ans=-INF;
    for(int j=1;j<=m;++j)
        cin>>s[j],s[j]+=s[j-1];
    for(int j=m,MAX=-INF;j;--j)
        MAX=max(MAX,s[j]),l[j]=MAX-s[j-1];
    for(int j=1,MIN=INF;j<=m;++j)
        MIN=min(MIN,s[j-1]),r[j]=s[j]-MIN;
    for(int i=1;i<n;++i)
    {
        a[m+1]=b[m+1]=c[0]=d[0]=-INF;
        for(int j=1;j<=m;++j)
            cin>>s[j],s[j]+=s[j-1];
        for(int j=m,MAX=-INF;j;--j)
            MAX=max(MAX,s[j]),a[j]=max(a[j+1],l[j]+MAX);
        for(int j=m,MAX=-INF;j;--j)
            b[j]=max(b[j+1],r[j]+MAX),MAX=max(MAX,s[j]);
        for(int j=1,MIN=INF;j<=m;++j)
            c[j]=max(c[j-1],l[j]-MIN),MIN=min(MIN,s[j-1]);
        for(int j=1,MIN=INF;j<=m;++j)
            MIN=min(MIN,s[j-1]),d[j]=max(d[j-1],r[j]-MIN);
        for(int j=1;j<=m;++j)
            l[j]=-s[j-1]+max(a[j+1],b[j]);
        for(int j=1;j<=m;++j)
            r[j]=s[j]+max(c[j],d[j-1]);
    }
    for(int j=1;j<=m;++j) ans=max(ans,l[j]);
    cout<<ans<<'\n';return ;
}
signed main()
{
#ifndef ONLINE_JUDGE
    freopen("in.in","r",stdin);
    freopen("out.out","w",stdout);
#endif
    cin.tie(0),cout.tie(0);
    ios::sync_with_stdio(0);
    cin>>T;while(T--) work();return 0;
}
posted @ 2024-10-08 17:09  int_R  阅读(101)  评论(0编辑  收藏  举报