首先我想验证一下我这个想法可不可以,题解里都是以 2as[i] 为斜率维护上凸包,我想以 −2as[i] 维护下凸包不知道可不可以,然后就是这个代码了,一直不对,求救谢谢。
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define CHECK cout<<"WALKED"<<endl;
#define ls u<<1
#define rs u<<1|1
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
ll qpow(ll a, ll b, ll mod){ll res = 1; while (b > 0){if (b & 1) res = res * a % mod;a = a * a % mod; b >>= 1; } return res;}
using namespace std;
const int N = 1e6 + 5;
int n, a, b, c;
ll s[N], f[N], q[N], h , t;
inline ll dx(int i, int j) { return s[i] - s[j];}
inline ll dy(int i, int j) { return (b * s[i] - a * s[i] * s[i] - f[i]) -
(b * s[j] - a * s[j] * s[j] - f[j]);}
int main()
{
scanf("%d %d %d %d", &n, &a, &b, &c);
for (int i = 1; i <= n; i++) {
scanf("%lld", &s[i]);
s[i] += s[i - 1];
}
for (int i = 2; i <= n ; i++) { // i from 1 or 2
int now_k = -2 * a * (s[i] - s[i - 1]); // watch out
while (h < t && dy(q[h], q[h + 1]) <= now_k * dx(q[h], q[h + 1]))
h++;
int j = q[h];
f[i] = f[j] + a * (s[i] - s[j]) * (s[i] - s[j]) + b * (s[i] - s[j]) + c;
while (h < t && dy(q[t], i) * dx(q[t - 1], q[t]) <= dy(q[t - 1], q[t]) * dx(q[t], i))
t--;
// t - i, t - 1 - i
q[++t] = i;
}
printf("%lld\n", f[n]);
return 0;
}