Advertisement
Dang_Quan_10_Tin

LEAVES

Aug 9th, 2020
181
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.53 KB | None | 0 0
  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <vector>
  5. #include <cstring>
  6. #define task "LEAVES"
  7. using namespace std;
  8. using ll = long long;
  9. using ld = long double;
  10.  
  11. const int N = 1e5 + 2;
  12. const ll Inf = 1e9;
  13. int n, k, last[15];
  14. ll a[N], d[N], f[N];
  15. ll dp[N][15];
  16. vector<int> line[15];
  17. vector<ld> point[15];
  18.  
  19. void Read(){
  20.     cin >> n >> k;
  21.     for(int i = 1; i <= n; ++i)
  22.         cin >> a[i];
  23.     reverse(a + 1, a + n + 1);
  24.     for(int i = 1; i <= n; ++i)
  25.         d[i] = d[i - 1] + a[i],
  26.         f[i] = f[i - 1] + a[i] * i,
  27.         cout << a[i] << " ";
  28.     cout << "\n";
  29. }
  30.  
  31. /// dp(i, t) = d(j) * (-i) + dp(j, t - 1) + f(j) + [ i * d(i) - f(i) ]
  32. /// Có thể coi [i * d(i) - f(i)] là 1 hằng số tăng vì nó phụ thuộc vào i và đổi với mi j, do vậy bài này là dp convex
  33.  
  34. ld ff(int t, int i, int j){
  35.     return (ld) 1.0 * (dp[i][t] + f[i] - dp[j][t] - f[j]) / (d[j] - d[i]);
  36. }
  37.  
  38. void Solve(){
  39.     fill_n(&dp[0][0], N * 15, Inf);
  40.     dp[0][0] = 0;
  41.     line[0].push_back(0);
  42.     for(int i = 0; i <= k; ++i)
  43.         point[i].push_back(-Inf);
  44.     for(int i = 1; i <= n; ++i){
  45.         for(int j = min(i, k); j; --j){
  46.             while(last[j - 1] < point[j - 1].size() && point[j - 1][last[j - 1]] < -i)
  47.                 ++last[j - 1];
  48.             --last[j - 1];
  49.             dp[i][j] = d[line[j - 1][last[j - 1]]] * (-i) + d[i] * i - f[i] +
  50.                        f[line[j - 1][last[j - 1]]] + dp[line[j - 1][last[j - 1]]][j - 1];
  51.             while(line[j].size() > 1){
  52.                 if(ff(j, i, line[j][line[j].size() - 1]) <= ff(j, i, line[j][line[j].size() - 2])){
  53.                     line[j].pop_back();
  54.                     point[j].pop_back();
  55.                     continue;
  56.                 }
  57.                 break;
  58.             }
  59.             last[j] = min(last[j], (int)point[j].size() - 1);
  60.             if(line[j].size())
  61.                 point[j].push_back(ff(j, i, line[j].back()));
  62.             line[j].push_back(i);
  63.         }
  64.     /*  cout << i << ": ";
  65.         for(int j = 1; j <= k; ++j)
  66.             cout << dp[i][j] << " ";
  67.         cout << "\n";
  68.         for(int i = 1; i <= k; ++i){
  69.         cout << " " << i << ": ";
  70.         for(auto j : line[i])
  71.             cout << j << " ";
  72.         cout << "\n";
  73.     }
  74.         //cout << "\n";*/
  75.     }
  76.     cout << dp[n][k];
  77.  
  78. }
  79.  
  80. void Bruteforces(){
  81.     fill_n(&dp[0][0], N * 15, Inf);
  82.     dp[0][0] = 0;
  83.     for(int i = 1; i <= n; ++i){
  84.         cout << "\n" << i << ": ";
  85.         for(int t = 1; t <= k; ++t){
  86.             for(int j = 0; j < i; ++j)
  87.                 dp[i][t] = min(dp[i][t], dp[j][t - 1] + (d[i] - d[j]) * i - (f[i] - f[j]));
  88.             cout << dp[i][t] << " ";
  89.         }
  90.     }
  91.     cout << dp[n][k];
  92. }
  93.  
  94. main(){
  95.     ios::sync_with_stdio(0);
  96.     cin.tie(0);
  97.     cout.tie(0); if(fopen(task".INP", "r"))
  98.     freopen(task".INP", "r", stdin),
  99.     freopen(task".OUT", "w", stdout);
  100.     Read();
  101.     Solve();
  102.     //Bruteforces();
  103. }
  104.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement