1563: [NOI2009]诗人小G

1563: [NOI2009]诗人小G

https://lydsy.com/JudgeOnline/problem.php?id=1563

分析:

  直接转移f[i]=f[j]+cost(i,j),cost(i,j)=(sum[i]-sum[j])p

  然后有决策单调性,就可以二分+队列了。注意两个字符串之间还有一个空格,所以长度+1,很多字符串合起来后,总的长度还要-1,最后一个没空格。

  证明?byvoid

  luogu输出方案,加上后一直过不了,g,nxt数组是输出方案的部分

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<cctype>
 7 #include<set>
 8 #include<vector>
 9 #include<queue>
10 #include<map>
11 #define fi(s) freopen(s,"r",stdin);
12 #define fo(s) freopen(s,"w",stdout);
13 using namespace std;
14 typedef long long LL;
15 typedef long double LD;
16  
17 inline int read() {
18     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
19     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
20 }
21  
22 const int N = 100005;
23 const LL INF = 1e18;
24  
25 char str[N][32], pr[25];
26 int len[N], g[N], nxt[N];
27 LD f[N];
28 LL sum[N];
29 int n, Len, P;
30 struct Node{
31     int p, l, r;
32     Node() {}
33     Node(int _,int __,int ___) { p = _, l = __, r = ___; }
34 }q[N];
35  
36 LD ksm(LD x) {
37     LD ans = 1; int b = P;
38     while (b) {
39         if (b & 1) ans = ans * x;
40         x = x * x;
41         b >>= 1;
42     }
43     return ans;
44 }
45 void init() {
46     n = read(), Len = read(), P = read();
47     for (int i=1; i<=n; ++i) {
48         scanf("%s", str[i] + 1); 
49         sum[i] = sum[i - 1] + (len[i] = strlen(str[i] + 1) + 1); 
50     }
51 }
52 LD Calc(int i,int j) {
53     return f[j] + ksm(abs(sum[i] - sum[j] - Len - 1));
54 }
55 int binary_search(int l,int r,int x,int y) {
56     int ans = n;
57     while (l <= r) {
58         int mid = (l + r) >> 1;
59         if (Calc(mid, x) < Calc(mid, y)) ans = mid, r = mid - 1;
60         else l = mid + 1;
61     }
62     return ans;
63 }
64 void solve() {
65     int L = 1, R = 0;
66     q[++R] = Node(0, 1, n);
67     for (int i=1; i<=n; ++i) {
68         while (L <= R && q[L].r < i) L ++;
69         int j = q[L].p; 
70         f[i] = Calc(i, j); 
71         g[i] = j;
72         if (Calc(n, q[R].p) < Calc(n, i)) continue; // 如果最后一个点从i转移不优,那么说明i没有覆盖的区间,不需要二分了
73         while (L <= R && Calc(q[R].l, q[R].p) > Calc(q[R].l, i)) R --;
74         q[R].r = binary_search(q[R].l, n, i, q[R].p) - 1;
75         q[++R] = Node(i, q[R - 1].r + 1, n);
76     }
77 }
78 void print() {
79       if (f[n] > INF) puts("Too hard to arrange");
80     else printf("%lld
", (LL)(f[n]));
81     puts(pr);
82 }
83 int main() {
84     strcpy(pr, "--------------------");
85     int T = read();
86     while (T--) {
87         init(); 
88         solve();
89         print();
90     }
91     return 0;
92 }
原文地址:https://www.cnblogs.com/mjtcn/p/9774761.html