「CF1101F」Trucks and Cities
题意描述
有 \(N\) 座城市,第 \(i\) 座坐标为 \(a_i\) ,有 \(M\) 辆卡车,第 \(i\) 辆卡车要从城市 \(s_i\) 前往城市 \(e_i\) ,每单位长度耗油量为 \(c_i\) ,可以在中途城市加满油 \(r_i\) 次,求让所有卡车都能到达目的地最小的油箱容积。
传送门
思考&做法
step 1
先来思考暴力,二分答案,然后check所有车,时间 \(O(MN\log 10^{18})\) ,会 \(\text{TLE}\) 。
到这,就有了多个分支,有大佬改换思路用 \(\text{dp}\),用四边形不等式推决策单调性优化 \(\text{dp}\) ,也有大佬用分别二分并随机化加剪枝优化暴力的,这些当时我都没有想到,就瞪大眼睛硬做这道题。
step 2
苦思冥想的时候,yangbaich给了我一个思路:在二分 \(V\) 后首先会预处理 \(f_{i, j}\) 表示在容量为 \(V\) 时,从城市 \(i\) 到城市 \(j\) ,途中不加油,\(c\) 最大是多少,然后暴力是每次加油一次并跳一格,我们要不 \(\text{TLE}\) 就要每次不止跳一格,这时我们或许就会想到倍增,但怎么构建倍增表呢?发现对于卡车 \(i\) ,只会走 \(f_{u, v} \ge c_i\) 的边 \((u, v)\) ,所以考虑对于 \(f\) 按 \(f_{u, v}\) 从大到小排序,卡车按 \(c_i\) 从大到小排序,然后双指针运动,保证在遍历到第 \(i\) 辆卡车时会加入所有该卡车能走的边,并且没有该卡车不能走的边。
step3
本来以为能做了,只不过每次要加边,倍增表只能静态,那怎么做呢?如果没有「CF13E」Holes的经验其实很难想到动态修改的跳表。思路就是按索引分块,对于每个元素维护一个 \(nxt_i\) 表示从 \(i\) 跳一步后的位置,\(jump_i\) 表示从 \(i\) 第一次跳到下一个块的位置,\(step_i\) 表示从 \(i\) 第一次跳到下一个块的过程中跳了多少步,每次修改 \(nxt_i\) 就对所有 \(j \in [L_{bel_i}, i]\) 修改 \(jump_j\) 为 \(jump_{nxt_j} + 1\) 或 \(nxt_j\) ,分讨,并赋值 \(step_j\) 。
在查询的时候,跳的过程中每次check当前 \(r\) 是否小于 \(step_u\) ,若小,跳出循环,暴力跳 \(r\) 次 \(nxt_i\) ,返回当前点 \(u\) ,然后看 \(u\) 是否大于 \(e_i\) ,若所有卡车都大于,返回 \(\text{true}\) ,反之返回 \(\text{false}\) 。
概括
二分答案,将卡车和预处理的 \(f\) 表按 \(c_i\) 和 \(f_{i, j}\) 从大到小排序,并用双指针依次加入 \(f_{u, v}\) 的边 \((u, v)\) 并保证 \(\forall f_{u, v} > c_i\) ,用分块维护跳表,让每一辆卡车跳 \(r\) 次,check落点 \(u\) 是否大于 \(e_i\) 。
总时间复杂度 \(O(M \sqrt{N} \log 10^{18})\)
solution
/*
address:https://codeforces.com/problemset/problem/1101/F
AC 2025/1/21 11:40
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 405, M = 2.5e5 + 5;
const LL INF = 1e18;
int a[N];
int n, m;
struct truck {
int s, f, c, r;
bool operator < (const truck& o)const { return c > o.c; }
}c[M];
struct node {
int x, y;
LL c;
bool operator < (const node& o)const { return c > o.c; }
}e[N * N];
int siz, blk;
int bel[N], nxt[N], jump[N], step[N], L[N], R[N];
inline void change(int id, int x) {
nxt[id] = x;
// printf("change %d -> %d ", id, x);
for (int i = id;i >= L[bel[id]];i--)
if (nxt[i] > R[bel[i]]) step[i] = 1, jump[i] = nxt[i];
else step[i] = step[nxt[i]] + 1, jump[i] = jump[nxt[i]];
// printf("step:%d\n", step[id]);
}
inline int lift(int id, int x) {
while (true) {
if (x < step[id]) break;
x -= step[id];
id = jump[id];
// printf("%d ", id);
}
for (int i = 1;i <= min(x, siz);i++) id = nxt[id];
// puts("");
return id;
}
inline bool check(LL v) {
// printf("%lld:\n", v);
int t = 0;
for (int i = 1;i <= n;i++)
for (int j = i + 1;j <= n;j++)
e[++t] = { i, j, v / (a[j] - a[i]) };
sort(e + 1, e + t + 1);
// for (int i = 1;i <= t;i++) printf("%d %d %lld\n", e[i].x, e[i].y, e[i].c);
for (int i = 1;i <= n;i++) nxt[i] = jump[i] = i, step[i] = N;
int j = 1;
for (int i = 1;i <= m;i++) {
// printf("truck %d:", i);
while (e[j].c >= c[i].c && j <= t) {
change(e[j].x, e[j].y);
j++;
}
// puts("");
int u = lift(c[i].s, c[i].r + 1);
if (u < c[i].f) return false;
}
return true;
}
int main() {
scanf("%d%d", &n, &m);
siz = sqrt(n);
blk = (n + siz - 1) / siz;
for (int i = 1;i <= n;i++) scanf("%d", &a[i]);
for (int i = 1;i <= n;i++) bel[i] = (i + siz - 1) / siz;
for (int i = 1;i <= blk;i++) L[i] = (i - 1) * siz + 1, R[i] = min(i * siz, n);
for (int i = 1;i <= m;i++) scanf("%d%d%d%d", &c[i].s, &c[i].f, &c[i].c, &c[i].r);
sort(c + 1, c + m + 1);
LL l = 1, r = INF, v = INF;
while (l <= r) {
LL mid = l + r >> 1;
if (check(mid)) r = mid - 1, v = mid;
else l = mid + 1;
}
printf("%lld", v);
return 0;
}
总结
不知道为什么,与yangbaich做题总能做出一些奇奇怪怪的做法,只不过这样也有益于拓展思维,希望后面不知只是按题解所说去做,能多有一些自己的思考并实践。
「CF1101F」Trucks and Cities的更多相关文章
- 「译」JUnit 5 系列:条件测试
原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...
- 「译」JUnit 5 系列:扩展模型(Extension Model)
原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...
- JavaScript OOP 之「创建对象」
工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...
- 「C++」理解智能指针
维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...
- 「JavaScript」四种跨域方式详解
超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...
- 「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management
写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...
- 「2014-3-18」multi-pattern string match using aho-corasick
我是擅(倾)长(向)把一篇文章写成杂文的.毕竟,写博客记录生活点滴,比不得发 paper,要求字斟句酌八股结构到位:风格偏杂文一点,也是没人拒稿的.这么说来,arxiv 就好比是 paper 世界的博 ...
- 「2014-3-17」C pointer again …
记录一个比较基础的东东-- C 语言的指针,一直让人又爱又恨,爱它的人觉得它既灵活又强大,恨它的人觉得它太过于灵活太过于强大以至于容易将人绕晕.最早接触 C 语言,还是在刚进入大学的时候,算起来有好些 ...
- 「2014-3-13」Javascript Engine, Java VM, Python interpreter, PyPy – a glance
提要: url anchor (ajax) => javascript engine (1~4 articles) => java VM vs. python interpreter =& ...
- 「2014-2-26」Unicode vs. UTF-8 etc.
目测是个老问题了.随便一搜,网上各种总结过.这里不辞啰嗦,尽量简洁的备忘一下. 几个链接,有道云笔记链接,都是知乎上几个问题的摘录:阮一峰的日志,1-5 还是值得参考,但是之后的部分则混淆了 Wind ...
随机推荐
- golang之操作kafka
安装第三方包: go get github.com/IBM/sarama 生产者实例: package main import ( "fmt" "github.com/I ...
- PTA-1002
原先主要错误: 没有考虑到有关0的相关情况 观看的大佬代码 整理思路 无非就是在相同的指数的情况下,系数相加 因为最后是要从大到小输出来. 注意 要对最后的结果进行四舍五入: PTA的英语题对英语不好 ...
- Astro Zen Blog |一个优雅、极简、强大的博客
介绍 Astro Zen 博客项目 如果你想部署一个自己的静态博客,又不想到处折腾,并且是熟悉的前端技术栈,你可以尝试下:Astro Zen Blog! Astro Zen Blog 是一个使用 As ...
- 切换浏览器tab刷新实现
标签: js 缘起 最近在做一个活动需求,需求交互有跨项目,跳转到另一个项目里完成指定任务,再回来领取相应任务奖励,产品十分反感要求用户主动刷新浏览器才更新活动页的任务信息. 解决方案 方案1:如果项 ...
- 【相邻不同型贪心】LeetCode767 重构字符串
题解 通常直接思考最佳策略是十分困难的,我们不妨思考每一种情况需要如何处理: 整个字符串只有一种字符 若字符串长度为 \(1\),那么字符串本身即为答案: 若字符串长度大于等于 \(2\),那么不存在 ...
- 在 .NET 下,Fiddler 不再抓取 Web Service 流量问题
在 .NET 下,Fiddler 不再抓取 Web Service 流量问题 问题现象 原来的一个应用中,需要访问 SOAP 服务.在原来的 .NET Framework 版本中,使用 Fiddler ...
- TypeScript 源码详细解读(2)词法1-字符处理
本节文章研究的代码位于 tsc/src/compiler/scanner.ts 字符 任何源码都是由很多字符组成的,这些字符可以是字母.数字.空格.符号.汉字等-- 每一个字符都有一个编码值,比如字符 ...
- ORM框架与数据库交互
title: ORM框架与数据库交互 date: 2024/12/22 updated: 2024/12/22 author: cmdragon excerpt: 对象关系映射(Object-Rela ...
- 黑苹果(Hackintosh) - 问题,修改CPU数量和内存数量后,系统重启失败
1. 问题复现 安装完黑苹果后,内存默认的 1个处理器2个核心.2G内存,发现不够用. 于是,修改了 VMware 对此系统的 硬件配置 内存: 2G -> 8G 处理器:1个处理器 -> ...
- Qt开源作品27-鼠标定位十字线
一.前言 上次有个群友在咨询这个问题,如何用Qt绘制一个鼠标定位的十字线,花了两分钟整了个,最没有含金量的一个demo,就是用drawline绘制了两条线,这个效果在经典的CAD软件中很常用,还有一些 ...