当前位置:网站首页>【luogu P1912】诗人小G(二分栈)(决策单调性优化DP)
【luogu P1912】诗人小G(二分栈)(决策单调性优化DP)
2022-08-01 20:04:00 【SSL_TJH】
诗人小G
题目链接:luogu P1912
题目大意
给你 n 句词,每一句有长度。
然后你可以选择把若干首连续的句子放在一行,用空格隔开。
然后一行的费用是它的长度(算上空格),跟标准长度的绝对值的 P 次方。
一首诗的一个方法的费用是每行的费用和。
然后要你求一首诗的最小费用,如果超过 1e18 特判一下,否则输出诗排布的方式。
思路
考虑 DP,设 f i f_i fi 把前 i i i 句放好的费用。
然后 n 2 n^2 n2 转移。
f i = min { f j + ( s i − s j − 1 − L ) P } f_{i}=\min\{f_{j}+(s_i-s_{j}-1-L)^P\} fi=min{ fj+(si−sj−1−L)P}
(其中 s s s 是前缀,包含空格,用 s i = s i − 1 + ∣ a i ∣ + 1 s_{i}=s_{i-1}+|a_i|+1 si=si−1+∣ai∣+1 来转移)
然后你想想一下就不难发现它满足决策单调性。
然后你思考一下会发现它不太是那种直接单调的,所以我们要用一个叫做二分栈的东西。
(因为它是根据 s j + 1 + L s_j+1+L sj+1+L 这个直线对称的,去掉绝对值变成两部分)
然后这里说说二分栈是啥:
就是你考虑对于栈中两个相邻的决策点,你通过二分得到一个临界值,在前面是这个优,后面是那个优。
(每次要加一个的时候就先判断栈顶和它下面那个,栈顶的话就是新准备要加进去的二分)
代码
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1e5 + 100;
const int P = 101;
int n, L, p, sz[N], a[N], sta[N], R[N], fr[N];
char s[N][P];
long double f[N];
int abs(int x) {
return x < 0 ? -x : x;}
long double ksm(long double x, int y) {
long double re = 1.0;
while (y) {
if (y & 1) re = re * x; x = x * x; y >>= 1;
}
return re;
}
long double clac(int l, int r) {
return f[l] + ksm((long double)abs(a[r] - a[l] - 1 - L), p);
}
int Get_pl(int x, int y) {
int l = x, r = n, re = n + 1;
while (l <= r) {
int mid = (l + r) >> 1;
if (clac(x, mid) >= clac(y, mid)) re = mid, r = mid - 1;
else l = mid + 1;
}
return re;
}
void dfs(int now) {
if (!now) return ;
dfs(fr[now]);
for (int i = fr[now] + 1; i <= now; i++) {
for (int j = 1; j <= sz[i]; j++) putchar(s[i][j]);
if (i != now) putchar(' '); else putchar('\n');
}
}
void slove() {
scanf("%d %d %d", &n, &L, &p);
for (int i = 1; i <= n; i++) {
scanf("%s", s[i] + 1); sz[i] = strlen(s[i] + 1);
a[i] = a[i - 1] + sz[i] + 1;
}
int l = 1, r = 1;
for (int i = 1; i <= n; i++) {
while (l < r && R[sta[l]] <= i) l++;
f[i] = clac(sta[l], i); fr[i] = sta[l];
while (l < r && R[sta[r - 1]] >= Get_pl(sta[r], i)) r--;
R[sta[r]] = Get_pl(sta[r], i);
sta[++r] = i;
}
if (f[n] > 1e18) printf("Too hard to arrange\n");
else {
printf("%.0Lf\n", f[n]);
dfs(n);
}
}
int main() {
int T; scanf("%d", &T);
while (T--) {
slove();
printf("--------------------\n");
}
return 0;
}
边栏推荐
猜你喜欢
随机推荐
Compose实战-实现一个带下拉加载更多功能的LazyColumn
【节能学院】推进农业水价综合改革的意见解读
Failed to re-init queues : Illegal queue capacity setting (abs-capacity=0.6) > (abs-maximum-capacity
Batch get protein .pdb files based on Uniprot ID/PDB ID
An implementation of an ordered doubly linked list.
[Energy Conservation Institute] Comparative analysis of smart small busbar and column head cabinet solutions in data room
useful website
【无标题】
Addition, Subtraction, Multiplication of Large Integers, Multiplication and Division of Large Integers and Ordinary Integers
Pytorch模型训练实用教程学习笔记:二、模型的构建
【多任务优化】DWA、DTP、Gradnorm(CVPR 2019、ECCV 2018、 ICML 2018)
我的驾照考试笔记(3)
openresty 动态黑白名单
SIPp installation and use
Acrel-5010重点用能单位能耗在线监测系统在湖南三立集团的应用
【torch】张量乘法:matmul,einsum
57: Chapter 5: Develop admin management services: 10: Develop [get files from MongoDB's GridFS, interface]; (from GridFS, get the SOP of files) (Do not use MongoDB's service, you can exclude its autom
MongoDB快速上手
30-day question brushing plan (5)
洛谷 P2440 木材加工