划分
m
y
y
myy
myy证明
这道题其他博客已经讲的很清楚了,就是发现这个转移满足单调性然后能满足后面的一定满足前面。
主要讲讲为什么单调队列的转移为什么是
q
[
l
+
1
]
q[l+1]
q[l+1]而不是
q
[
l
]
q[l]
q[l],由这道题目转移的性质,我们要把这道题决策点的转移尽量卡满(能靠右一定要靠右),那如果满足单调队列里队头决策点的下一个决策点能转移,那么当前队头决策点就一定能被弹掉。如果
q
[
l
]
q[l]
q[l]被弹掉了
q
[
l
+
1
]
q[l+1]
q[l+1]不一定能满足,那么这道题单调队列转移就会出问题。同时
q
[
l
+
1
]
q[l+1]
q[l+1]比
q
[
l
]
q[l]
q[l]更靠近
i
i
i(单调队列里保存的决策最优点保存的是下标),那么前者构成的前缀和一定比后者更小,如果这样能满足转移条件的话才能保证一定是最优决策。
88
p
t
s
88pts
88pts代码,反正高精我在考场上想出来了多半也没时间写
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+50;
int n,type,l=0,r=0,sum[N],q[N],pre[N],dp[N];
int x;
inline int read(){
int cnt=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-f;c=getchar();}
while(isdigit(c)){cnt=(cnt<<1)+(cnt<<3)+(c^48);c=getchar();}
return cnt*f;
}
inline int val(int pos){return 2*sum[pos]-sum[pre[pos]];}
signed main(){
n=read(),type=read();
for(int i=1;i<=n;++i) x=read(),sum[i]=sum[i-1]+x;
q[++r]=0;
for(int i=1;i<=n;++i){
while(l<r&&val(q[l+1])<=sum[i]) ++l;
pre[i]=q[l];
dp[i]=dp[pre[i]]+(sum[i]-sum[pre[i]])*(sum[i]-sum[pre[i]]);
while(l<=r&&val(i)<=val(q[r]))--r;
q[++r]=i;
}
cout<<dp[n]<<endl;
return 0;
}