1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
   |  const int maxn = 100000 + 5; int N, L, P;
  class Q { public:     int x, l, r; }; Q q[maxn];
  ld f[maxn]; ll S[maxn];
  void init() {     Set(f, 0);     Set(S, 0); }
  ld cal(int i, int j) {     ld ans = 1;     ld num = abs((ld)(S[i] - S[j] + i - j - 1 - L));     _rep(k, 1, P) ans *= num;     return ans + f[j]; }
  int bsearch(int i, int ql, int qr) {     int ans = 0;     while (ql <= qr) {         int mid = (ql + qr) >> 1;         if(q[mid].l <= i && q[mid].r >= i) {             ans = mid;             break;         }         if(q[mid].l <= i) ql = mid + 1;         else qr = mid - 1;     }
      return q[ans].x; }
  int findpos(int i, int x, int l, int r) {     while (l < r) {         int mid = (l + r) >> 1;         if (cal(mid, i) > cal(mid, x)) l = mid + 1;         else r = mid;     }     return l; }
  void insert(int i, int& ql, int& qr) {     int pos = -1;     while (ql <= qr) {         int lt = q[qr].l, rt = q[qr].r, xt = q[qr].x;         if(cal(lt, i) <= cal(lt, xt)) pos = q[qr--].l;         else {             if(cal(rt, i) < cal(rt, xt)) {                 pos = findpos(i, xt, q[qr].l, q[qr].r);                 q[qr].r = pos - 1;             }             break;         }     }
      if(pos != -1) {         q[++qr].l = pos;         q[qr].r = N;         q[qr].x = i;     } }
  void solve() {     init();     cin >> N >> L >> P;
      // == get poetry sentences ==     _rep(i, 1, N) {         char str[35];         scanf("%s", str);         S[i] = S[i - 1] + strlen(str);     }     // == poetry sentences finished ==
      // == monotonic dp ==     int ql = 1, qr = 1;     q[1].x = 0;     q[1].l = 1;     q[1].r = N;
      _rep(i, 1, N) {         int j = bsearch(i, ql, qr);         if(i == 1) assert(j == 0);         f[i] = cal(i, j);
          // == then pop front and try to insert i ==         while (ql <= qr && q[ql].r <= i) ql++;         q[ql].l = i + 1;         insert(i, ql, qr);         // == monotonic queue finished ==     }     // == monotonic finished ==
      if(f[N] > 1e18) puts("Too hard to arrange");     else cout << (ll)f[N] << endl;
      _rep(i, 1, 20) putchar('-');     cout << endl; }
  int main() {     freopen("input.txt", "r", stdin);     int T;     cin >> T;     while (T--) solve(); }
 
  |