当前位置:网站首页>【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;
}
边栏推荐
猜你喜欢

17. Load balancing

nacos installation and configuration

泰德制药董事长郑翔玲荣膺“2022卓越影响力企业家奖” 泰德制药荣获“企业社会责任典范奖”

LTE time domain and frequency domain resources

【多任务模型】Progressive Layered Extraction: A Novel Multi-Task Learning Model for Personalized(RecSys‘20)

【torch】张量乘法:matmul,einsum

Use WeChat official account to send information to designated WeChat users

第58章 结构、纪录与类

Creo5.0 rough hexagon is how to draw

我的驾照考试笔记(4)
随机推荐
【无标题】
【Untitled】
Addition, Subtraction, Multiplication of Large Integers, Multiplication and Division of Large Integers and Ordinary Integers
【节能学院】智能操控装置在高压开关柜的应用
Batch get protein .pdb files based on Uniprot ID/PDB ID
【torch】张量乘法:matmul,einsum
使用微信公众号给指定微信用户发送信息
泰德制药董事长郑翔玲荣膺“2022卓越影响力企业家奖” 泰德制药荣获“企业社会责任典范奖”
不同的操作加不同的锁详解
【节能学院】数据机房中智能小母线与列头柜方案的对比分析
【ES】ES2021 我学不动了,这次只学 3 个。
XSS range intermediate bypass
数据可视化
Determine a binary tree given inorder traversal and another traversal method
第56章 业务逻辑之物流/配送实体定义
OSPO 五阶段成熟度模型解析
Application of Acrel-5010 online monitoring system for key energy consumption unit energy consumption in Hunan Sanli Group
To promote energy conservation institute 】 【 the opinions of the agricultural water price reform
18. Distributed configuration center nacos
小数据如何学习?吉大最新《小数据学习》综述,26页pdf涵盖269页文献阐述小数据学习理论、方法与应用