http://www.lydsy.com/JudgeOnline/problem.php?id=1010
斜率优化DP
设dp[i]表示前i个玩具装箱所需的最小耗费
dp[i] = min(dp[j]+(i-j-1+∑C[k]-L)^2)
设sc[i] = ∑C[k] ( 1<= k <= i)
则有
dp[j]+(i-j-1+∑C[k]-L)^2
= dp[j]+(i-j-1+sc[i]-sc[j]-L)^2
= dp[j]+((i-1+sc[i]-L)-(sc[j]+j))^2
= dp[j]+(i-1+sc[i]-L)^2+(sc[j]+j)^2-2*(i-1+sc[i]-L)*(sc[j]+j)
用y表示dp[j]+(sc[j]+j)^2
用x表示sc[j]+j
用a表示2*(i-a+sc[i]-L)
G = -ax+y,其中a是单调递增的,满足斜率优化的条件
则dp[i] = min(G)+i-1+sc[i]-L
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <queue> #include <algorithm> #include <vector> #include <cstring> #include <stack> #include <cctype> #include <utility> #include <map> #include <string> #include <climits> #include <set> #include <string> #include <sstream> #include <utility> #include <ctime> #include <bitset> using std::priority_queue; using std::vector; using std::swap; using std::stack; using std::sort; using std::max; using std::min; using std::pair; using std::map; using std::string; using std::cin; using std::cout; using std::set; using std::queue; using std::string; using std::stringstream; using std::make_pair; using std::getline; using std::greater; using std::endl; using std::multimap; using std::deque; using std::unique; using std::lower_bound; using std::random_shuffle; using std::bitset; using std::upper_bound; using std::multiset; typedef long long LL; typedef unsigned long long ULL; typedef pair<int, int> PAIR; typedef multimap<int, int> MMAP; typedef LL TY; typedef long double LF; const int MAXN(50010); const int MAXM(100010); const int MAXE(100010); const int MAXK(6); const int HSIZE(31313); const int SIGMA_SIZE(26); const int MAXH(19); const int INFI((INT_MAX-1) >> 1); const ULL BASE(31); const LL LIM(10000000); const int INV(-10000); const int MOD(20100403); const double EPS(1e-7); const LF PI(acos(-1.0)); template<typename T> void checkmax(T &a, T b){if(b > a) a = b;} template<typename T> void checkmin(T &a, T b){if(b < a) a = b;} template<typename T> T ABS(const T &a){return a < 0? -a: a;} int que[MAXN]; int front, back; LL sc[MAXN]; LL table[MAXN]; LL Y(int ind){return table[ind]+(ind+sc[ind])*(ind+sc[ind]);} LL X(int ind){return ind+sc[ind];} int main() { int N, L; while(~scanf("%d%d", &N, &L)) { for(int i = 1; i <= N; ++i) { scanf("%lld", sc+i); sc[i] += sc[i-1]; } LL ans = 1e12; front = 0; back = -1; que[++back] = 0; for(int i = 1; i <= N; ++i) { LL temp =i-1+sc[i]-L; LL a = 2*temp; while(back-front > 0 && (-a)*X(que[front+1])+Y(que[front+1]) <= (-a)*X(que[front])+Y(que[front])) ++front; table[i] = (-a)*X(que[front])+Y(que[front])+temp*temp; while(back-front > 0 && (Y(i)-Y(que[back-1]))*(X(i)-X(que[back])) >= (Y(i)-Y(que[back]))*(X(i)-X(que[back-1]))) --back; que[++back] = i; } printf("%lld\n", table[N]); } return 0; }