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;
}