首页 > 其他分享 >文件排版 题解

文件排版 题解

时间:2024-08-28 11:30:10浏览次数:7  
标签:文件 pw int 题解 单词 -- 排版 图片

前言

题目链接:HDU

题意简述

给 \(n\) 个单词和一张图片排版。每个单词长度为 \(a_i\)。图片占行不确定,但是占列始终为 \([dw + 1, dw + pw]\)。排版宽度为 \(W\),高度无限制。要求单词间有长度为 \(1\) 的空格,单词不能超出宽度 \(W\),不能覆盖在图片上,单词间相对顺序不能发生改变。有 \(Q\) 次询问,给出 \(x_i, h_i\) 表示图片占行为 \([x_i + 1, x_i + h_i]\),求出在此基础上有多少行存在图片或字符。

\(n, W, Q \leq 10^5\)。

题目分析

每次询问如果直接 \(\Theta(n)\) 扫一遍肯定会超时,那我们要做的就是优化加速这一过程。

我们发现,对于一行来说,只会有被图片覆盖或者不被图片覆盖两种状态,并且由于图片占行固定,那么所有行的这两种状态都是确定的。每一次扫过一行都要重新计算,无疑就是冗余的了。

我们可以预处理出 \(f_i, g_i\) 表示以第 \(i\) 个单词为开头的行,这一行有或没有被图片占,下一行的开始是什么。至于如何预处理,使用双指针即可。

这样,我们时间复杂度就取决于排版的行数了。还是不够。发现我们排版经历的过程为三个大步骤:没被图片覆盖、被图片覆盖、没被图片覆盖。在同一个步骤,我们不断让 \(i \gets f_i\),做的是同一件事,并且是一个转移的过程,所以很容易想到使用倍增优化。

如此,我们最终时间复杂度就是:\(\Theta(Q \log n)\) 的。

注意有些情况需要特判,在代码中标出了。

代码

#include <cstdio>
#include <iostream>
using namespace std;

int n, W, pw, lw, rw, q;

int tr1[100010][19], tr2[100010][19];
//  没有放图片        放置了图片
long long len[100010];

void solve() {
	scanf("%d%d%d%d", &n, &W, &pw, &lw), rw = W - pw - lw;
	for (int i = 1; i <= n; ++i) {
		scanf("%lld", &len[i]);
		len[i] += len[i - 1];  // 前缀和
	}
	tr1[n + 1][0] = tr2[n + 1][0] = n + 1;
	for (int l = 1, r = 1; l <= n; ++l) {
		while (r + 1 <= n && len[r + 1] - len[l - 1] + r + 1 - l <= W) ++r;
		tr1[l][0] = r + 1;
	}
	for (int l = 1, m = 0, r = 0; l <= n; ++l) {
		while (m + 1 <= n && len[m + 1] - len[l - 1] + m + 1 - l <= lw) ++m;
		r = max(r, m);
		while (r + 1 <= n && len[r + 1] - len[m] + r - m <= rw) ++r;
		tr2[l][0] = r + 1;
	}
	for (int k = 1; k <= 18; ++k) {
		for (int i = 1; i <= n + 1; ++i) {
			tr1[i][k] = tr1[tr1[i][k - 1]][k - 1];
			tr2[i][k] = tr2[tr2[i][k - 1]][k - 1];
		}
	}
	int non = 1;  // 完全不放图片的行数
	for (int cur = 1, k = 18; k >= 0; --k)
		if (tr1[cur][k] <= n) {
			non += 1 << k;
			cur = tr1[cur][k];
		}
	scanf("%d", &q);
	for (int x, h; q--; ) {
		scanf("%d%d", &x, &h), --x;
		if (x >= non) {  // 说明图片和文字间有空行,做特判
			printf("%d\n", non + h);
			continue;
		}
		int cur = 1, ans = x + h;
		for (int k = 18; k >= 0; --k)
			if ((1 << k) <= x)  // 先把图片之前的单词放了
				cur = tr1[cur][k], x -= 1 << k;
		for (int k = 18; k >= 0; --k)
			if ((1 << k) <= h)  // 现在做被图片占了的行的转移
				cur = tr2[cur][k], h -= 1 << k;
		if (cur > n) {  // 放完了
			printf("%d\n", ans);
			continue;
		}
		for (int k = 18; k >= 0; --k)
			if (tr1[cur][k] <= n)  // 否则就继续放图片,直到放完
                ans += 1 << k, cur = tr1[cur][k];
		printf("%d\n", ans + 1);  // 加上最后跳出的那一步
	}
}

signed main() {
	int t; scanf("%d", &t);
	while (t--) solve();
	return 0;
}

总结 & 反思

遇到多次进行同一个操作,并且是在不断“跳”的过程,可以使用倍增优化。

标签:文件,pw,int,题解,单词,--,排版,图片
From: https://www.cnblogs.com/XuYueming/p/18384157

相关文章

  • 题解 [ABC199F] Graph Smoothing(中文/English)
    本题解提供英文版,位于示例代码之后。Englishversionofthiseditorialisprovidedafterthesamplecode.设行向量:\[A^{(k)}=\begin{bmatrix}a_1^{(k)}&a_2^{(k)}&\cdots&a_n^{(k)}\end{bmatrix}\]表示\(k\)次操作后每个节点点权的期望。特别地,\(A^{(0)}\)表......
  • 适用于多语言的VScode配置教程:同一文件夹内支持C++, JAVA, Python
    前言VScode作为一款强大的文本编辑器,只要配置恰当,便可以同时在一个环境内编译多种语言的文件。本文简要给出一种同时支持C++,Python,Java的配置方式(windows平台)。配置格式1.创建工作区并建立如图的文件夹及文件结构其中包括vscode的配置文件夹.vscode,以及其他三个代码文件......
  • MD5值修改器 无须安装,解压即用,可修改图片/视频/文件/程序MD5值
    分享一个我一直在用的MD5值修改器给大家,此修改器无须下载,解压即用,操作简单,下面我一步步操作给大家看如何通过修改器修改MD5值1、点击BatchMD5Modify.exe,打开修改器主页打开后的界面是这样的2、点击添加要修改MD5值的视频、图片、文件、程序,并选择打开添加3、点击修改,看......
  • 网闸实现ftp文件同步
    网闸网闸作为一种安全产品双主机结构:一般采用两台相互隔离的主机以及一个独立硬件单芯片传输:隔离外部数据通过摆渡芯片将外网主机与内网主机的数据进行交换共享没有默认策略没有安全域的划分只是将网络划分为内网外网两部分内外网之间交互必须通过网闸的摆渡芯片传输......
  • 基于PHP的文件上传
    文件上传是现代网络应用中不可或缺的功能,它允许用户将本地文件存储到服务器上,用于后续的处理、分发或备份。一、基于前端验证的文件上传文件上传漏洞中的前端验证漏洞是一个常见且危险的问题。这类漏洞的产生主要是因为前端验证机制可以通过多种方式被绕过,从而使得攻击者能......
  • 接口获取文件流VUE转换为blob展示图片
    接口获取文件流VUE转换为blob展示图片vue通过接口获取图片文件流<template><el-image:src="imgurl"alt="资源访问失败"width="80%"height="80%"style="display:block"/></template><scriptsetup>importax......
  • Go实现大文件分片上传
    index.html<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>uploadfile</title></head><bodyid="app"><h1style="text-align:center"&......
  • 递推配套P1192 & 题解:P1192 台阶问题
    我们现在考虑递推。现在的问题是,如何从前几个数据推导出下一个数据。我们现在先推导\(f(n)\)。设\(k=3\)。到\(n\)的方法就是到能一步到\(n\)的台阶的方法总和,所以我们可以推导出:\(f(n)=f(n-1)+f(n-2)+\dots+f(n-k)/f(1)\)。即为:\(f(n)=\sum_{i=......
  • 如何将文件或文件夹压缩为7-Zip格式?
    ​7-Zip压缩包的优势就是可以将文件压缩的相比其他格式压缩包的体积更小,大家也很喜欢使用,今天讲一下如何将文件压缩胃7-Zip压缩包首先,我们可以使用7-Zip压缩软件进行压缩,下载7-Zip压缩软件之后右键点击想要压缩的文件,选择7-Zip-添加到压缩包软件默认为7z格式,如果我们想要......
  • 【一文详解】内外网文件摆渡系统,解决网间数据安全传输问题
    一、内外网文件摆渡系统的背景数字化转型进一步推动了数据的移动,而随着攻击者加速利用日常生活中的数据依赖性,数据泄露也随之扩大。企业为保护网络安全和数据安全,使用网络隔离手段进行网络隔离,如银行内部将网络隔离为生产网、办公网、DMZ区;如生物制药企业、医院等机构将网络隔离......