题目大意:
#include <bits/stdc++.h> #define N 500005 using namespace std; int n,m,dp[N],deq[N],sum[N]; // deq[]为单调队列 sum[]为数组的前缀和 int DP(int i,int j) { return dp[j]+m+(sum[i]-sum[j])*(sum[i]-sum[j]); } int UP(int j,int k) { //yj-yk的部分 return dp[j]+sum[j]*sum[j]-(dp[k]+sum[k]*sum[k]); } int DOWN(int j,int k) {//xj-xk的部分 return 2*(sum[j]-sum[k]); } /* 由分析 当0<a<b<i时 若(ya-yb)/(xa-xb)<sum[i] 此处表达为G(a,b)<sum[i] 则j优于k 若存在a,b和b,c满足上述要求 即存在G(a,b)<sum[i] G(b,c)<sum[i] 若G(a,b)<G(b,c) 则b肯定不为最优点 */ int main() { while(~scanf("%d%d",&n,&m)) { sum[0]=dp[0]=0; for(int i=1;i<=n;i++) { int num; scanf("%d",&num); sum[i]=sum[i-1]+num; } int head=0, tail=0; deq[tail++]=0; for(int i=1;i<=n;i++) { while(head+1<tail && UP(deq[head+1],deq[head])<=sum[i] *DOWN(deq[head+1],deq[head])) head++; /// G(head+1,head)<=sum[i] 即head+1优于head 则去掉head dp[i]=DP(i,deq[head]); // 用此时的最优head更新dp[i] while(head+1<tail && UP(i,deq[tail-1])*DOWN(deq[tail-1],deq[tail-2]) <=DOWN(i,deq[tail-1])*UP(deq[tail-1],deq[tail-2])) tail--; /// 如果此时G(i,tail-1)<=G(tail-1,tail-2)<=sum[i] 则说明tail-1对应点为可删去 deq[tail++]=i; } printf("%d\n",dp[n]); } return 0; }/*纠结了一下维护单调队列时为什么判断条件是<=第一处 G(head+1,head)=sum[i] 说明 两者平等 不存在谁更优这个问题而仍然 head++; 是因为既然两者平等 那么只要留一个就可以了第二处 G(i,tail-1)=G(tail-1,tail-2) 说明 两者斜率相等 即 i,tail-1,tail-2 三个对应点在同一条直线上那么 tail-1 这个点可以直接忽略 所以继续 tail--;*/
原文地址:https://www.cnblogs.com/zquzjx/p/9162040.html
时间: 2024-11-04 22:28:16