当前位置:网站首页>【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;
}
边栏推荐
- Redis does web page UV statistics
- 【kali-信息收集】(1.3)探测网络范围:DMitry(域名查询工具)、Scapy(跟踪路由工具)
- 面试突击70:什么是粘包和半包?怎么解决?
- The Internet giant development process
- 二维、三维、四维矩阵每个维度含义解释
- 【多任务优化】DWA、DTP、Gradnorm(CVPR 2019、ECCV 2018、 ICML 2018)
- 【ES】ES2021 我学不动了,这次只学 3 个。
- KDD2022 | Self-Supervised Hypergraph Transformer Recommendation System
- 我的驾照考试笔记(1)
- 环境变量,进程地址空间
猜你喜欢
安全作业7.25
Get started quickly with MongoDB
Use WeChat official account to send information to designated WeChat users
Little data on how to learn?Jida latest small learning data review, 26 PDF page covers the 269 - page document small data learning theory, method and application are expounded
Greenplum数据库源码分析——Standby Master操作工具分析
nacos installation and configuration
【多任务学习】Modeling Task Relationships in Multi-task Learning with Multi-gate Mixture-of-Experts KDD18
第58章 结构、纪录与类
[Multi-task model] Progressive Layered Extraction: A Novel Multi-Task Learning Model for Personalized (RecSys'20)
环境变量,进程地址空间
随机推荐
[Energy Conservation Institute] Comparative analysis of smart small busbar and column head cabinet solutions in data room
解除360对默认浏览器的检测与修改
myid file is missing
Software you should know as a programmer
nacos installation and configuration
Wildcard SSL/TLS certificate
环境变量,进程地址空间
nacos安装与配置
【kali-信息收集】(1.3)探测网络范围:DMitry(域名查询工具)、Scapy(跟踪路由工具)
How PROE/Croe edits a completed sketch and brings it back to sketching state
网络不通?服务丢包?这篇 TCP 连接状态详解及故障排查,收好了~
SIPp 安装及使用
我的驾照考试笔记(4)
LTE time domain and frequency domain resources
【无标题】
Ruijie switch basic configuration
[Personal work] Wireless network image transmission module
【节能学院】数据机房中智能小母线与列头柜方案的对比分析
【kali-信息收集】(1.6)服务的指纹识别:Nmap、Amap
OSPO 五阶段成熟度模型解析