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 }