Maximum Monogonosity
Hisaishi_Kanade · · 题解
这种题在场上没做出来我还是挺飞舞的。
设
转移则是简单的,
这个东西
我们发现,如果要选
但是我们发现还有个绝对值不太好搞,我们将
我们将只和
对于第一条,由于
对于第二条,绝对值所有取值情况都枚举过了,而且最开始枚举了一个不取的情况,所以是成立的。
那么代码比较显然了。
#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for(i=l; i<=r; ++i)
const int N=3005, K=3005;
using ll=long long;
vector<ll> mxa, mxb, mxc, mxd;
/*
- + a - +
+ + b - -
- - c + +
+ - d + -
*/
long long f[N][K], a[N], b[N];
int n, k, i, j, t;
long long ret;
const ll inf=-(1ll<<50);
int main()
{
scanf("%d", &t);
while(t--)
{
ret=0;
scanf("%d %d", &n, &k);
rep(i, 1, n) scanf("%lld", a+i); a[n+1]=0;
rep(i, 1, n) scanf("%lld", b+i); b[n+1]=0;
vector<ll>(n+5, inf).swap(mxa); vector<ll>(n+5, inf).swap(mxb);
vector<ll>(n+5, inf).swap(mxc); vector<ll>(n+5, inf).swap(mxd);
rep(i, 0, n) rep(j, 0, n) f[i][j]=inf;
f[0][0]=0; mxa[0]=-a[1]+b[1]; mxb[0]=a[1]+b[1]; mxc[0]=-a[1]-b[1]; mxd[0]=a[1]-b[1];
rep(i, 1, n)
{
rep(j, 0, k)
{
if(j>i) break;
f[i][j]=max(f[i][j], f[i-1][j]);
f[i][j]=max(f[i][j], -a[i]+b[i]+mxa[i-j]);// printf("%d %d\n",mxa[i-j],f[i][j]);
f[i][j]=max(f[i][j], -a[i]-b[i]+mxb[i-j]);// printf("%d\n",f[i][j]);
f[i][j]=max(f[i][j], +a[i]+b[i]+mxc[i-j]);// printf("%d\n",f[i][j]);
f[i][j]=max(f[i][j], +a[i]-b[i]+mxd[i-j]);// printf("%d\n",f[i][j]);
if(i!=n)
{
mxa[i-j]=max(mxa[i-j], f[i][j]-a[i+1]+b[i+1]);
mxb[i-j]=max(mxb[i-j], f[i][j]+a[i+1]+b[i+1]);
mxc[i-j]=max(mxc[i-j], f[i][j]-a[i+1]-b[i+1]);
mxd[i-j]=max(mxd[i-j], f[i][j]+a[i+1]-b[i+1]);
}
ret=max(ret, f[i][j]);
}
}
printf("%lld\n", ret);
}
}