BZOJ 1563 四边形不等式

Description

Input

Output

对于每组数据,若最小的不协调度不超过1018,则第一行一个数表示不协调度若最小的不协调度超过1018,则输出"Too hard to arrange"(不包含引号)。每个输出后面加"--------------------"

Sample Input

4
4 9 3
brysj,
hhrhl.
yqqlm,
gsycl.
4 9 2
brysj,
hhrhl.
yqqlm,
gsycl.
1 1005 6
poet
1 1004 6
poet

Sample Output

108
--------------------
32
--------------------
Too hard to arrange
--------------------
1000000000000000000
--------------------

【样例说明】
前两组输入数据中每行的实际长度均为6,后两组输入数据每行的实际长度均为4。一个排版方案中每行相邻两个句子之间的空格也算在这行的长度中(可参见样例中第二组数据)。每行末尾没有空格。

HINT

总共10个测试点,数据范围满足:

测试点 T N L P
1 ≤10 ≤18 ≤100 ≤5
2 ≤10 ≤2000 ≤60000 ≤10
3 ≤10 ≤2000 ≤60000 ≤10
4 ≤5 ≤100000 ≤200 ≤10
5 ≤5 ≤100000 ≤200 ≤10
6 ≤5 ≤100000 ≤3000000 2
7 ≤5 ≤100000 ≤3000000 2
8 ≤5 ≤100000 ≤3000000 ≤10
9 ≤5 ≤100000 ≤3000000 ≤10
10 ≤5 ≤100000 ≤3000000 ≤10
所有测试点中均满足句子长度不超过30。

 

四边形不等式优化dp使用条件:

若dp[i] = Min(dp[j] + val(i, j)), 如果val(i, j)满足(val(i, j) + val(i + 1, j + 1) <= val(i, j + 1) + val(i + 1, j),即val满足四边形不等式,则该dp方程满足决策单调性。

即对每一个dp[i],其转移过来的位置p[i]序列有单调性。

利用决策单调性,将复杂度降低至nlogn。

具体操作:

建一个元素为(x, l, r)(表示l ~ r之间的dp值最优决策都是由位置x处转移)的队列。

(1) 每次更新检查队头的r是否为i - 1,如果是,踢掉;否则更新队头的l值为i;

(2)直接取队头的x值更新dp[i],即dp[i] = dp[x] + val(i, x);

接下来要维护队尾满足决策单调

(3)如果队尾的l, x满足dp[x] + val(l, x) > dp[i] + val(l, i) 踢掉; 不断重复此操作

(4)在队尾的区间内二分得到最小的ans(默认r + 1),使得dp[i] + val(ans, i) < dp[x] + val(ans, x);

(5)更改队尾r为ans - 1;队尾加入(i, ans, n)

 1 #include <iostream>
 2 #include <fstream>
 3 #include <sstream>
 4 #include <cstdlib>
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <string>
 8 #include <cstring>
 9 #include <algorithm>
10 #include <queue>
11 #include <stack>
12 #include <vector>
13 #include <set>
14 #include <map>
15 #include <list>
16 #include <iomanip>
17 #include <cctype>
18 #include <cassert>
19 #include <bitset>
20 #include <ctime>
21 
22 using namespace std;
23 
24 #define pau system("pause")
25 #define ll long long
26 #define pii pair<int, int>
27 #define pb push_back
28 #define mp make_pair
29 #define mp make_pair
30 #define pli pair<ll, int>
31 
32 const double pi = acos(-1.0);
33 const int INF = 0x3f3f3f3f;
34 const int MOD = 1e9 + 7;
35 const double EPS = 1e-9;
36 
37 /*
38 #include <ext/pb_ds/assoc_container.hpp>
39 #include <ext/pb_ds/tree_policy.hpp>
40 using namespace __gnu_pbds;
41 #define tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> TREE
42 TREE T;
43 */
44 
45 const int M = 1018;
46 int T, n, l, p, a[100015], sum[100015];
47 long double dp[100015];
48 struct gg {
49         int x, l, r;
50         gg () {}
51         gg (int x, int l, int r) : x(x), l(l), r(r) {}
52 } g[100015];
53 int ql, qr;
54 char s[35];
55 long double val(int i, int j) {
56         return dp[j] + pow(abs(sum[i] - sum[j] + i - j - 1 - l), p);
57 }
58 int main() {
59     scanf("%d", &T);
60     while (T--) {
61             scanf("%d%d%d", &n, &l, &p);
62             for (int i = 1; i <= n; ++i) {
63                     scanf("%s", s);
64                     a[i] = strlen(s);
65                     sum[i] = sum[i - 1] + a[i];
66             }
67             g[ql = qr = 1] = gg(0, 1, n);
68             for (int i = 1; i <= n; ++i) {
69                     if (g[ql].r == i - 1) ++ql;
70                     else g[ql].l = i;
71                     int j = g[ql].x;
72                     long double x = abs(sum[i] - sum[j] + i - j - 1 - l);
73                     dp[i] = dp[j] + pow(x, p);
74                     while (ql <= qr) {
75                             int tl = g[qr].l, j = g[qr].x;
76                             if (val(tl, j) > val(tl, i)) --qr;
77                             else break;
78                     }
79                     int s = g[qr].l, e = g[qr].r, ans = e + 1, mi;
80                     j = g[qr].x;
81                     while (s <= e) {
82                             mi = s + e >> 1;
83                             if (val(mi, j) > val(mi, i)) e = (ans = mi) - 1;
84                             else s = mi + 1;
85                     }
86                     g[qr].r = ans - 1;
87                     if (ans <= n) g[++qr] = gg(i, ans, n);
88             }
89             if (dp[n] <= 1e18) {
90                     printf("%lld\n", (ll)dp[n]);
91             } else {
92                     puts("Too hard to arrange");
93             }
94             puts("--------------------");
95     }
96     return 0;
97 }
View Code

 

posted @ 2018-09-23 18:03  hit_yjl  阅读(148)  评论(0编辑  收藏  举报