斜率优化
斜率优化这个玄学的东西, 其实都是模板,至少用单调队列维护时是这样的...
一.玩具装箱
怕是斜率优化的入门题
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> using namespace std; #define int long long int n, L; int c[50005], sum[50005]; int f[50005]; double abss(double a) { return a < 0 ? -a : a; } int A(int i) { return sum[i] + i; } int B(int i) { return A(i) + L + 1; } int X(int i) { return B(i); } int Y(int i) { return B(i) * B(i) + f[i]; } int G(int i) { return A(i); } double slope(int a, int b) { return ((double)(Y(b) - Y(a)) / (double)(X(b) - X(a))); } int q[50005], l = 1, r = 1; signed main() { cin >> n >> L; for(register int i = 1 ; i <= n ; i ++) { scanf("%lld", &c[i]); sum[i] = sum[i-1] + c[i]; } for(register int i = 1; i <= n ; i ++) { while(l < r && slope(q[l], q[l+1]) < G(i) * 2) l++; int j = q[l]; f[i] = Y(j) - 2 * G(i) * X(j) + A(i) * A(i); while(l < r && slope(q[r-1], q[r]) > slope(q[r-1], i)) r--; q[++r] = i; } printf("%lld\n", f[n]); return 0; }
二.特别行动队
其实也特别水
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; #define int long long int n, a, b, c; int sum[1000010]; int q[1000011], l, r; int f[1000010];//考虑到第i个士兵的最大战斗力. //f[i] = f[i-1], f[i] = max(f[j] + a*(sum[i] - sum[j])^2 + b*(sum[i]-sum[j])+c); //f[i] = Y(i) - G(i) * X(j) + D; //X(i) = sum[i]; //Y(i) = f[i] - b * sum[i] + a * sum[i] ^ 2; //G(i) = 2 * a * sum[i]; //D = a * sum[i]^2 + b * sum[i] + c; int G(int i) { return 2 * a * sum[i]; } int X(int i) { return sum[i]; } int Y(int i) { return f[i] - b * sum[i] + a * sum[i] * sum[i]; } int D(int i) { return a * sum[i] * sum[i] + b * sum[i] + c; } double slope(int a, int b) { return((double)(Y(b) - Y(a)) / (double)(X(b) - X(a))); } signed main() { cin >> n >> a >> b >> c; for(register int i = 1 ; i <= n ; i ++) { int t ; scanf("%lld", &t); sum[i] = sum[i-1] + t; } for(register int i = 1 ; i <= n ; i ++) { while(l < r && slope(q[l], q[l+1]) > G(i)) l++; int j = q[l]; f[i] = Y(j) - G(i) * X(j) + D(i); while(l < r && slope(q[r-1], q[r]) <=slope(q[r], i)) r--; q[++r] = i; //f[i] = max(f[i], f[i-1]); } cout << f[n]; return 0; }
三.仓库建设
水的不行
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; #define maxn 1000010 #define int long long int n, x[maxn], p[maxn], c[maxn]; int sum[maxn], s[maxn]; int f[maxn]; inline int G(int i) { return x[i]; } inline int X(int i) { return sum[i]; } inline int D(int i) { return c[i] - s[i] + x[i] * sum[i]; } inline int Y(int i) { return f[i] + s[i]; } inline double slope(int a, int b) { return ((double)(Y(b) - Y(a)) / (double)(X(b) - X(a))); } int q[maxn], l, r; signed main() { cin >> n; for (int i = 1; i <= n; i++){ scanf("%lld%lld%lld", &x[i], &p[i], &c[i]); sum[i] = sum[i-1] + p[i]; s[i] = s[i-1] + x[i] * p[i]; f[i] = 0x7f7f7f7f; } for (int i = 1; i <= n; i++){ while (l < r && slope(q[l], q[l+1]) < G(i)) l++; int j = q[l]; f[i] = Y(j) - G(i) * X(j) + D(i); while(l < r && slope(q[r-1], q[r]) > slope(q[r-1], i)) r--; q[++r] = i; } cout << f[n]; return 0; }