题解:P16499 【MX-S14-T2】「KWOI R2」染色
题目传送门
思路
动态规划。
状态定义
设 \(dp_{i,c}\) 表示:前 \(i\) 个元素,第 \(i\) 个元素被分到子序列 \(c\) 时,能获得的最大总得分。其中 \(c\) 为 \(0\) 或 \(1\),表示红和蓝。
转移方程
对于第 \(i\) 个元素 \(A_i\),它存在两种情况。
情况一:\(A_i\) 和上一个同色元素相连
假设第 \(i\) 个元素和第 \(j\) 个元素同色(\(j<i\)),且 \(A_j\) 是子序列 \(c\) 中在 \(A_i\) 左边,离 \(A_i\) 最近的元素,即当前与 \(A_i\) 相邻,则有:
\[dp_{i,c}=dp_{j,c}+|A_i-A_j|
\]
情况二:\(A_i\) 是当前颜色子序列的第一个元素
则 \(A_i\) 无法造成额外贡献,直接转移:
\[dp_{i,c}=\max_{k<i}\{dp_{k,1-c}\}
\]
优化
观察数据范围,这样的转移显然会超时,考虑优化。
观察转移方程:
\[dp_{i,c}=\max_{j<i}\{dp_{j,c}+|A_i-A_j|\}
\]
将绝对值拆开得:
- 若 \(A_j \leq A_i\),\(dp_{j,c}+|A_i-A_j|=dp_{j,c}+A_i-A_j=(dp_{j,c}-A_j)+A_i\)
- 若 \(A_j > A_i\),\(dp_{j,c}+|A_i-A_j|=dp_{j,c}+A_j-A_i=(dp_{j,c}+A_j)-A_i\)
所以我们只需要维护两个最大值:
- \(m=\max\{dp_{j,c}-A_j\}\)
- \(p=\max\{dp_{j,c}+A_j\}\)
于是转移方程变成了:
\[dp_{i,c}=\max(m+A_i,p-A_i)
\]
时间复杂度就变成线性的了,刚好通过数据。
代码
在实现中,其实可以不用数组存 \(dp_{i,0}\) 和 \(dp_{i,1}\),观察可得以下算法实现:
- 每步转移实际上是在维护一个额外得分 \(v\)。
- \(m\) 和 \(p\) 同上文维护最大值。
- \(ans\) 累加所有 \(|A_i-A_{i-1}|\) 作为基本得分。
- 记 \(maxn\) 为过程中所有 \(v\) 的最大值,则答案为 \(ans+maxn\)。
AC Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
int cid,test;
namespace FastIO {
char buf[1<<21], *p1=buf, *p2=buf;
inline int getch (void) {
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;
}
inline int read (void) {
int x = 0, f = 1, ch = getch();
while(!isdigit(ch)) {
if(ch == '-') f = -f;
ch = getch();
}
while(isdigit(ch)) {
x = x * 10 + ch - '0';
ch = getch();
}
return x * f;
}
char buf2[1<<21], buf3[25];
int tp_l, buf2_l=-1;
inline void flush (void) {
fwrite (buf2, 1, buf2_l+1, stdout), buf2_l=-1;
}
inline void print (long long x, char ch=10) {
if(buf2_l>(1<<20)) flush();
if(x<0) buf2[++buf2_l]='-', x=-x;
do buf3[++tp_l]=x%10+48;
while(x/=10);
do buf2[++buf2_l]=buf3[tp_l];
while(--tp_l);
buf2[++buf2_l] = ch;
}
}
using FastIO::read;
using FastIO::print;
int n,x,y,ans,maxn,mm,mp,b,t,v;
void solve()
{
n=read();
if(n==1)
{
read();
print(0);
return;
}
x=read();
ans=0,maxn=0,mm=-1e18,mp=-1e18;
for(int i=2;i<=n;i++)
{
y=read();
t=abs(y-x);
b=max(mm+y,mp-y);
v=max(b,0ll);
v-=t,ans+=t;
maxn=max(maxn,v);
mm=max(mm,v-x);
mp=max(mp,v+x);
x=y;
}
print(ans+maxn);
}
signed main(){
cid=read();test=read();
while(test--){
solve();
}
FastIO::flush();
return 0;
}

浙公网安备 33010602011771号