[关闭]
@ZCDHJ 2019-09-16T09:10:32.000000Z 字数 905 阅读 605

APIO2014 序列分割

未分类


可以发现切割顺序对答案没啥影响,那么默认从左到右切,就是很板子的斜率优化了。

  1. #include <iostream>
  2. #include <cstdio>
  3. typedef long long LL;
  4. #define int LL
  5. const int MAXN = 2e5;
  6. const int MAXK = 3e2;
  7. int n, k;
  8. int q[MAXN | 1], fa[MAXK | 1][MAXN | 1];
  9. LL a[MAXN | 1], dp[MAXK | 1][MAXN | 1];
  10. inline int read() {
  11. register int x = 0;
  12. register char ch = getchar();
  13. while (!isdigit(ch)) ch = getchar();
  14. while (isdigit(ch)) {
  15. x = x * 10 + ch - '0';
  16. ch = getchar();
  17. }
  18. return x;
  19. }
  20. inline double slope(int i, int x, int y) {
  21. if (a[x] == a[y]) return -1e18;
  22. return 1.0 * (dp[i][y] - a[y] * a[y] - (dp[i][x] - a[x] * a[x])) / (-a[y] + a[x]);
  23. }
  24. void out(int i, int j) {
  25. if (i == 0) return;
  26. out(i - 1, fa[i][j]);
  27. printf("%d ", fa[i][j]);
  28. }
  29. signed main() {
  30. n = read();
  31. k = read();
  32. for (int i = 1; i <= n; ++i) a[i] = a[i - 1] + read();
  33. for (int i = 1; i <= k; ++i) {
  34. int l = 1, r = 0;
  35. for (int j = 1; j <= n; ++j) {
  36. while (l < r && slope(i - 1, q[l], q[l + 1]) <= a[j]) ++l;
  37. dp[i][j] = dp[i - 1][q[l]] + (a[j] - a[q[l]]) * a[q[l]];
  38. fa[i][j] = q[l];
  39. while (l < r && slope(i - 1, q[r - 1], q[r]) >= slope(i - 1, q[r], j)) --r;
  40. q[++r] = j;
  41. }
  42. }
  43. printf("%lld\n", dp[k][n]);
  44. out(k, n);
  45. return 0;
  46. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注