首先对贡献进行一个基本的转化,设 A i = B i + C i A_i=B_i+C_i Ai=Bi+Ci,答案是 ∑ [ B i > B i + 1 ] + ∑ [ C i < C i + 1 ] \sum [B_i>B_{i+1}]+\sum [C_i<C_{i+1}] ∑[Bi>Bi+1]+∑[Ci<Ci+1]。
设 d p i , j dp_{i,j} dpi,j表示 B i = j B_i=j Bi=j时的最小代价,我们从两个角度压缩状态。
1.1
1.1
1.1
∣
d
p
i
,
0
−
d
p
i
,
A
i
∣
≤
2
|dp_{i,0}-dp_{i,A_i}|\le 2
∣dpi,0−dpi,Ai∣≤2 ,显然,因为这一步最多产生
2
2
2的贡献,也就是说值域是稠密的。
1.2
1.2
1.2
d
p
i
,
j
dp_{i,j}
dpi,j单调递减。
上述性质不难通过打表看出。并且 j j j固定时, k k k越大,转移代价越大,所以我们大力维护这个分段函数即可。
复杂度 O ( n ) O(n) O(n)。注意如果 B B B的后缀是 0 0 0或者 C C C的前缀是 0 0 0时会多算贡献,需要处理一下边界。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,a[200005];
int x,y,dp;
signed main(){
cin>>n;for(int i=1;i<=n;i++)cin>>a[i];
y=a[1];
for(int i=2;i<=n;i++){
int l1=max(y,a[i]-a[i-1]+y); // 代价为0
int l2=min(y,a[i]-a[i-1]+y); // 代价为1
int l3=max(x,a[i]-a[i-1]+x),l4=min(y-1,a[i]-a[i-1]+y-1);
int X=0,Y=0;
if(l1>a[i]){
dp++,Y=l2;
if(l3<=l4)Y=l3;
}
else {
Y=l1,X=l2;
if(l3<=l4)X=l3;
}
x=max(X,0),y=max(Y,0);
}if(y==0)dp--;
cout<<dp+1;
}