BZOJ 1010: [HNOI2008]玩具装箱toy
思路:
斜率优化dp
s[i]表示1-i的前缀和
斜率不等式为:
对于 i < j < k
(dp[j] - dp[k] + (j + s[j])^2 - (k + s[k])^2) / ((j + s[j]) - (k + s[k])) <= 2*(i + s[i] - l -1)
#include<bits/stdc++.h> using namespace std; #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pii pair<int, int> #define piii pair<pii, int> #define mem(a, b) memset(a, b, sizeof(a)) #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout); //head const int N = 5e4 + 5; int c[N], l; LL sum[N], dp[N]; LL get_down(int j, int k) { return (j + sum[j] - (k + sum[k])); } LL get_up(int j, int k) { return dp[j] - dp[k] + (j + sum[j])*(j + sum[j]) - (k + sum[k])*(k + sum[k]); } int main() { int n; scanf("%d %d", &n, &l); for (int i = 1; i <= n; i++) scanf("%d", &c[i]); for (int i = 1; i <= n; i++) { sum[i] = sum[i-1] + c[i]; } deque<int>q; q.push_front(0); for (int i = 1; i <= n; i++) { while(q.size() >= 2) { int t = q.front(); q.pop_front(); int tt = q.front(); if(get_up(tt, t) <= 2*(i + sum[i] - l - 1)*get_down(tt, t)); else { q.push_front(t); break; } } int t = q.front(); dp[i] = dp[t] + (i - t - 1 + sum[i] - sum[t] - l) * (i - t - 1 + sum[i] - sum[t] - l); while(q.size() >= 2) { int t = q.back(); q.pop_back(); int tt = q.back(); if(get_up(i, t) * get_down(t, tt) <= get_up(t, tt) * get_down(i, t)) ; else { q.push_back(t); break; } } q.push_back(i); } printf("%lld\n", dp[n]); return 0; }