P1912 [NOI2009] 诗人小G 题解

我们设 \(s_i\) 表示前 \(i\) 个句子的长度之和,这样就有 dp

\[f_i = \min_{j < i} \big\{f_j + |s_i - s_j + i - j - 1 - L|^P\big\} \]

我们设 \(w(l, r) = |s_r - s_l + r - l - 1 - L|^ P\),如果 \(w\) 满足四边形不等式,则原 dp 具有决策单调性。

\(u = (s_i + i) - (s_j + j ) - (1 + L)\), \(v = (s_i + i) - (s_j + j + 1 + a_j) - (1 + L)\)

那么我们证明 \((j < j + 1 < i < i + 1 )\)

\[w(j, i) + w(j + 1, i + 1) \le w(j, i + 1) + w(j + 1, i) \]

等价于证明

\[|u|^P + |v + a_i+1|^P \le |v|^P +|u+a_i+1|^P \\ |u|^P - |u + a_i+1|^P \le |v|^P - |v + a_i+1| \]

因为 \(a_j > 0\),所以 \(u > v\),如果我们设 \(h(x) =|x|^P - |x+z|^P\),那么如果 \(h(x)\) 单调不增,则原命题成立。

证明如下:

我们对绝对值进行讨论。

  • \(x \in [0, \infty)\)

\[h(x)=x^P - (x+z)^P \\ h'(x) = Px^{P - 1} - P(x + z)^{P - 1} \\ h'(x) = P[x^{P - 1} - (x+z)^{P - 1}] \\ h'(x) = P[x^{P - 1} - \sum_{i = 0}^{P - 1}\binom{P-1}{i}x^{P - 1 - i}z^i] \\ h'(x) = P[-\sum_{i = 1}^{P - 1}\binom{P-1}{i}x^{P - 1 - i}z^i] \\ \]

因为 \(P > 0, x > 0, z > 0\),所以 \(h'(x) \le 0, \Box\)

  • \(x \in (-\infty, 0)\)

注意到此时 \(P\) 的取值会影响到 \(x^P\) 的正负(实际上是 \(h'(x)\)\(x^{P - 1}\) 的正负),所以需要对 \(P\) 的奇偶性进行讨论。

  • \(x \in (-\infty, 0)\)\(P\) 为偶数时

\[h(x)=x^P - (x+z)^P \\ h'(x) = Px^{P - 1} - P(x + z)^{P - 1} \\ h'(x) = P[x^{P - 1} - (x+z)^{P - 1}] \\ \]

注意到只需证 $x^{P - 1} < (x+z)^{P - 1} $,两边同时取 \(\log_{P-1}\),因为 \(z > 0\),所以显然有 \(x < x + z\)

  • 当 $x \in [-z, 0) $ 时,\(P\) 为奇数时

\[h(x)=-x^P - (x+z)^P \\ h'(x) = -Px^{P - 1} - P(x + z)^{P - 1} \\ \]

注意到 \(P-1\) 为偶数,所以 \(x^{P-1} > 0\),所以 \(h'(x) \le 0\)

  • \(x \in [-\infty, -z)\) 时,\(P\) 为偶数时

\[h(x)=-x^P + (x+z)^P \\ h'(x) = -Px^{P - 1} + P(x + z)^{P - 1} \\ h'(x) = -P(x^{P - 1}-(x+z)^{P - 1}) \]

注意到只需证明 \(x^{P - 1} < (x+z)^{P - 1}\),显然成立,理由同上,所以 \(h'(x) \le 0\)

综上所述,\(h(x)\) 单调不增。

单调队列维护即可。

\(10^{18}\) 是一个卡的很死的上界,所以最好在过程中用 long double 舍弃精度判断是否大于 \(10^{18}\)

// 如果命运对你缄默, 那就活给他看。
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast", "inline", "-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
typedef long long LL; 
#define int LL
const int maxn = 1e5 + 10;
char s[maxn][40]; 	
int p[maxn], T, n, L, P, sl[maxn];
long double f[maxn];
long double fp(long double a, int b) {
	long double res = 1;
	for(; b; b >>= 1, a = a * a) 
		if(b & 1) res = res * a;
	return res;
}
inline long double g(int u, int p) {
	return f[p] + fp(abs(sl[u] - sl[p] - L - 1), P);
}
inline void clear() {
	memset(p, 0, sizeof p);
	memset(f, 0, sizeof f);
}
struct state {
	int p, l, r;
} q[maxn]; 
inline void solve() { 
	cin >> n >> L >> P;
	for(int i = 1; i <= n; ++ i) {
		cin >> s[i] + 1;
		sl[i] = sl[i - 1] + strlen(s[i] + 1) + 1;
	}
	int hh = 0, tt = -1;
	q[++ tt] = {0, 1, n};
	for(int i = 1; i <= n; ++ i) {
		while(hh <= tt && q[hh].r < i) hh ++ ;
		f[i] = g(i, q[hh].p), p[i] = q[hh].p;
		while(hh <= tt && g(q[tt].l, i) <= g(q[tt].l, q[tt].p)) tt -- ;
		int l = q[tt].l, r = n + 1;
		while(l < r) {
			int mid = l + r >> 1;
			if(g(mid, i) <= g(mid, q[tt].p)) r = mid;
			else l = mid + 1;
		}
		if(l > n) continue ;
		q[tt].r = l - 1;
		q[++ tt] = {i, l, n};
	}
	if(f[n] > 1e18) cout << "Too hard to arrange\n";
	else {
		cout << fixed << setprecision(0) << f[n] << '\n';
		stack <pair<int, int>> st;
		for(int x = n; x; x = p[x]) st.emplace(p[x] + 1, x);
		while(st.size()) {
			auto [l, r] = st.top();
			for(int i = l; i < r; ++ i) cout << (s[i] + 1) << ' ';
			cout << (s[r] + 1) << '\n';
			st.pop();
		} 
	}
	cout << "--------------------\n";
}
signed main() {
	ios :: sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	cin >> T;
	while(T -- ) clear(), solve();
	return 0;
}
posted @ 2024-07-18 12:03  Rainsheep  阅读(260)  评论(0编辑  收藏  举报