[HNOI2018]转盘

给你一个 \(n\) 元环, 你可以在 \(0\) 时刻从任意一个位置出发, 每一秒可以选择往后或者留在原地每个点有个参数 \(T_i\) , 当你走到 \(i\) 的时间 \(t\ge T_i\) 时你就可以把 \(i\) 标记问你把整个环上的点都标记最小需要多长时间, 带修改 \(T_i\), 强制在线.

\(\text{Solution:}\)

只看题目比较难发现其中的性质,我们来手模一下。

比如 \(T = 1, 2, 5, 4, 5​\)

标记每个点的时间为 \(1, 2, 5, 6, 7\)

显然 \(3, 4, 5, 6, 7\) 也是一组合法解。

这启示我们如果从将题目转换一下,变成:

假设你 \(t\) 时刻在某个点,每次可以向前走或者留在原地,然后 \(t\) 减 \(1\),开始所有的点都出现,每个点在 \(T_i\) 时间消失,求一个最小的 \(t\) 使得在所有点都消失前访问所有点.

显然一直走会不会更差,如 \(3, 4, 5, 6, 7\) 不会比 \(1, 2, 5, 6, 7\) 差。

这下时间就是连续的,这也方便我们讨论。


再次简化:

在一个长度为 \(2n\) 的序列上(断环成链),从点 \(i\in[n,2n)\)出发

\[\forall j\in(1,2n],\\
t-(i-j) \ge T_j\\
\Rightarrow t \ge T_j+i - j\\
\Rightarrow t_{min}= max\{ T_j-j\}+i
\]

求 \(t_{min}\)


仔细观察式子:

考虑枚举 \(j\) 看哪些 \(i\) 满足i的后缀最大值为 \(a_j\) ,从后往前扫,扫到一个数就更新后缀最大值,然后 \(chkmin\) 。

这样扫描每次 O(n),复杂度不对,没有充分利用每次修该前的信息,于是我们考虑将没有影响的一部分合并,可以用线段树来实现。

线段树每个节点维护该区间的最大 \(a\) ,以及答案,

向上合并的时候是在左区间递归找满足条件的 \(i​\) ,往左还是往右找分类讨论一下,再选取最小的答案即可(比较难理解画一画,想一想)。

#include <set>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <assert.h>
#include <algorithm> using namespace std; #define LL long long
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define GO debug("GO\n") inline int rint() {
register int x = 0, f = 1; register char c;
while (!isdigit(c = getchar())) if (c == '-') f = -1;
while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getchar()));
return x * f;
} template<typename T> inline void chkmin(T &a, T b) { a > b ? a = b : 0; }
template<typename T> inline void chkmax(T &a, T b) { a < b ? a = b : 0; } const int maxN = 2e5 + 10; int n, m, q;
int ans[maxN * 4], mx[maxN * 4], T[maxN]; #define ls (x<<1)
#define rs (x<<1|1) int query(int x, int l, int r, int y) {
if (l == r) return l + max(mx[x], y);
int mid = (l + r) >> 1;
if (mx[rs] >= y) return min(ans[x], query(rs, mid + 1, r, y));
else return min(mid + 1 + y, query(ls, l, mid, y));
} void pu(int x, int l, int r) {
mx[x] = max(mx[ls], mx[rs]);
ans[x] = query(ls, l, (l + r) >> 1, mx[rs]);
} void Build(int x, int l, int r) {
if (l == r) {
mx[x] = ans[x] = T[l] - l;
return;
}
int mid = (l + r) >> 1;
Build(ls, l, mid);
Build(rs, mid + 1, r);
pu(x, l, r);
} void change(int x, int l, int r, int y) {
if (l == r) {
ans[x] = mx[x] = T[l] - l;
return;
}
int mid = (l + r) >> 1;
if (y <= mid) change(ls, l, mid, y);
else change(rs, mid + 1, r, y);
pu(x, l, r);
} int main() {
#ifndef ONLINE_JUDGE
freopen("xhc.in", "r", stdin);
freopen("xhc.out", "w", stdout);
#endif
n = rint(), m = rint(), q = rint();
for (int i = 1; i <= n; ++ i)
T[i] = T[i + n] = rint();
Build(1, 1, n * 2);
int lastans = ans[1] + n - 1;
printf("%d\n", lastans);
while (m --) {
int x = rint(), y = rint();
if (q) x ^= lastans, y ^= lastans;
T[x] = T[x + n] = y;
change(1, 1, 2 * n, x);
change(1, 1, 2 * n, x + n);
lastans = ans[1] + n - 1;
printf("%d\n", lastans);
}
}

[HNOI2018]转盘的更多相关文章

  1. 【BZOJ5286】[HNOI2018]转盘(线段树)

    [BZOJ5286][HNOI2018]转盘(线段树) 题面 BZOJ 洛谷 题解 很妙的一道题目啊.(全世界除了我这题都有40分,就我是一个状压选手 首先来发现一些性质,我们走一圈一定不会更差. 为 ...

  2. 5286: [Hnoi2018]转盘

    5286: [Hnoi2018]转盘 链接 分析: $\min\limits_{i=1}^n \{ \max\limits_{j=i}^{i + n - 1} \{ a_{j}+i \} \} +n- ...

  3. [BZOJ5286][洛谷P4425][HNOI2018]转盘(线段树)

    5286: [Hnoi2018]转盘 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 15  Solved: 11[Submit][Status][Di ...

  4. bzoj 5286: [Hnoi2018]转盘

    Description Solution 首先注意到一个点不会走两次,只会有停下来等待的情况,把序列倍长 那么如果枚举一个起点\(i\),答案就是 \(min(max(T[j]+n-(j-i)-1)) ...

  5. BZOJ.5286.[AHOI/HNOI2018]转盘(线段树)

    BZOJ LOJ 洛谷 如果从\(1\)开始,把每个时间\(t_i\)减去\(i\),答案取决于\(\max\{t_i-i\}\).记取得最大值的位置是\(p\),答案是\(t_p+1+n-1-p=\ ...

  6. BZOJ5286: [Hnoi2018]转盘 (线段树)

    题意 给你绕成一圈的物品共 \(n\) 个 , 然后从其中一个开始选 , 每次有两种操作 , 一是继续选择当前物品 , 二是选择这个后一个物品 . 选择后一个物品要求当前的时刻大于后一个的 \(T_i ...

  7. [HNOI2018]转盘[结论+线段树]

    题意 题目链接 分析 首先要发现一个结论:最优决策一定存在一种 先在出发点停留之后走一圈 的情况,可以考虑如下证明: 如果要停留的话一定在出发点停留,这样后面的位置更容易取到. 走超过两圈的情况都可以 ...

  8. 【比赛】HNOI2018 转盘

    通过这题,我发现了我最大的缺陷,就是题目中重要的性质发现不了,所以导致后期根本做不了.还是要多做题,培养思维 对于这道题,来发现性质吧 对于每一条路线,因为它有用的就是最终的时刻,所以我们都可以把它变 ...

  9. 【题解】HNOI2018转盘

    何学长口中所说的‘一眼题’……然而实际上出出来我大HN全省也只有一个人A…… 首先我们需要发现一个性质:我们永远可以在最后一圈去标记所有的物品.倘若我们反复转圈,那么这完全是可以省下来的.所以我们破环 ...

随机推荐

  1. REST解惑

    本文是「架构风格:你真的懂REST吗?」的补充! REST全称是Representational State Transfer,目前普遍接受的中文翻译为「表述性状态转移」! 即使翻译过来了,你依然有一 ...

  2. 大数据框架-spark

    相关详细说明:https://www.csdn.net/article/2015-07-10/2825184 RDD:弹性分布式数据集. Operation:Transformation 和Actio ...

  3. PX4地面站QGroundControl在ubuntu下的安装

    1.引言 相信很多玩开源无人机的朋友手上都有一架无人机,而不是仅仅停留在理论的学习和程序的学习.放飞自己组装的无人机才是乐趣所在,那么这本文就介绍玩无人机必不可少的地面站软件qgroundcontro ...

  4. Linux - CentOS 7 yum方式快速安装MongoDB

    一.安装环境及配置yum # more /etc/redhat-release CentOS Linux release 7.2.1511 (Core) # vi /etc/yum.repos.d/m ...

  5. SQLMAP使用详解

    使用示例 python sqlmap.py -u "http://xx.com/member.php?id=XX"  -p id --dbms "Mysql"  ...

  6. python drf+xadmin+react+dva+react-native+sentry+nginx 搭建前后端分离的博客完整平台

    前言: 经过差不多半年的开发,搭建从前端到服务器,实现了前后端分离的一个集PC端.移动端的多端应用,实属不易,今天得空,好好写篇文章,记录这些天的成果.同时也做个分享. 演示网站地址: http:// ...

  7. vue项目出现空格警告的原因及其解决办法

    原因: 因为你的Webpack 配置中大概是使用了 eslint-loader,这是用来规范代码风格的,在多人协作或大项目中推荐使用,不想要则可以在 webpack.config.js 中去掉.esl ...

  8. git 码云 使用记录

    使用了码云的私有仓库. 一.首先下载安装git 安装完成后,在开始菜单里找到“Git”->“Git Bash”,蹦出一个类似命令行窗口的东西,就说明Git安装成功! 二.创建版本库 什么是版本库 ...

  9. memcache和redis的区别和联系

    一.区别 Memcache : 1,对每个key的数据最大是1M. 2,对各种技术支持比较全面,session可以存储memcache中,各种框架(例如thinkphp)对memcache支持比较好. ...

  10. node的安装和配置

    一 . 直接安装node 1. http://nodejs.cn/download/ 根据自己的电脑选择适合的安装包 2.安装 , 无脑下一步 , 可以选择安装路径 , 但是一定要记住 . 3.命令行 ...