Description

题库链接

在一个环上有 \(n\) 个物品,第 \(i\) 个物品的出现时间为 \(T_i\) 。一开始你可以任意选择一个物品的位置作为起始位置,然后以这个位置为起点沿正方向走,走一个单位花一个单位的时间,不能调头,可以停留。问至少多少时间可以取完所有的物品。一个物品 \(i\) 能被取当且仅当到达该物品的位置时时间 \(\geq T_i\) ,初始时间为 \(0\) 。支持 \(m\) 次单点修改,强制在线。

\(3\leq n\leq 10^5,0\leq m\leq 10^5\)

Solution

推推性质,容易得到这样的一个结论:不会走到相同的地方两次。换句话说就是相当于选定起点之后,每走到一个位置一定会等到该位置的物品出现取上该物品后再继续走。

感性证明下:考虑为什么会有不符合上述情况的走法,显然是一个离我较远的物品比离我较近的物品先出现,并且早的多,那么我就需要先去取较远的物品再走一圈回来取这个出现时间较晚的物品。不过这样的话,我可以直接把起点放在那个较远的物品处,显然答案不会比我这样走的答案差。

既然有这样的结论,我们先将数组倍长,可以枚举起点,再在起点向右枚举 \(n\) 个,统计一下最大值,最后取个最小值即可。不过这样单次操作就是 \(O(n^2)\) 的,肯定过不了...

考虑到答案就是求:

\[\min_{1\leq i\leq n}\left\{\max_{i\leq j\leq i+n-1}\left\{T_j+(n-1-(j-i))\right\}\right\}\]

其实这个是和式子

\[\min_{1\leq i\leq n}\left\{\max_{i\leq j\leq 2n}\left\{T_j+(n-1-(j-i))\right\}\right\}\]

是等价的。

将式子变一下形,记 \(a_i=T_i-i\)

\[\min_{1\leq i\leq n}\left\{\max_{i\leq j\leq 2n}\left\{a_j\right\}+i\right\}+n-1\]

考虑如何维护这个东西。

我们让线段树每个节点 \(o\) (控制区间为 \([l,r]\) )维护两个值 \(maxn_o\) 和 \(val_o\) 。表示区间 \(a_i\) 最值和 \(\min\limits_{l\leq i\leq mid}\left\{\max\limits_{i\leq j\leq r}\left\{a_j\right\}+i\right\}\) 。

考虑如何维护这个 \(val_o\) 。

对于每个线段树中的非叶子节点,我们需要合并左右儿子的信息。主要的就是考虑右儿子的值会对左儿子中的起点产生影响。

我们不妨记当前节点的右儿子的 \(maxn\) 为 \(mx\) 。

对于左儿子 \(ls\) ,如果他的右儿子的 \(maxn\geq mx\) ,显然 \(ls\) 的左儿子的 \(val\) 值可以直接用;右儿子无法确定,递归处理右儿子。

如果 \(ls\) 的右儿子的 \(maxn\leq mx\) ,显然 \(ls\) 的右儿子的内起点的最小值一定是 \(mid+1+mx\) ;左儿子无法确定,递归处理左儿子。

显然对于每次更新需要 \(\log\) 的递归询问。

至于更新,只要更新线段树一条链上的所有节点。线段树维护的总复杂度为 \(O(n\log_2^2 n)\) 。

Code

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N = 2e5+5;
  4. int n, m, p, t[N], a[N], x, y, last;
  5. struct Segment_tree {
  6. #define lr(o) (o<<1)
  7. #define rr(o) (o<<1|1)
  8. int maxn[N<<2], val[N<<2];
  9. int query(int o, int l, int r, int mx) {
  10. if (l == r) return l+max(mx, maxn[o]); int mid = (l+r)>>1;
  11. if (mx <= maxn[rr(o)]) return min(val[o], query(rr(o), mid+1, r, mx));
  12. else return min(mid+mx+1, query(lr(o), l, mid, mx));
  13. }
  14. void pushup(int o, int l, int mid, int r) {
  15. val[o] = query(lr(o), l, mid, maxn[rr(o)]);
  16. maxn[o] = max(maxn[lr(o)], maxn[rr(o)]);
  17. }
  18. void build(int o, int l, int r) {
  19. if (l == r) {maxn[o] = a[l], val[o] = l+a[l]; return; }
  20. int mid = (l+r)>>1;
  21. build(lr(o), l, mid), build(rr(o), mid+1, r);
  22. pushup(o, l, mid, r);
  23. }
  24. void update(int o, int l, int r, int loc) {
  25. if (l == r) {maxn[o] = a[l], val[o] = l+a[l]; return; }
  26. int mid = (l+r)>>1;
  27. if (loc <= mid) update(lr(o), l, mid, loc);
  28. else update(rr(o), mid+1, r, loc);
  29. pushup(o, l, mid, r);
  30. }
  31. }T;
  32. void work() {
  33. scanf("%d%d%d", &n, &m, &p);
  34. for (int i = 1; i <= n; i++)
  35. scanf("%d", &t[i]), a[i] = t[i]-i, a[i+n] = t[i]-n-i;
  36. T.build(1, 1, n<<1);
  37. printf("%d\n", last = T.val[1]+n-1);
  38. while (m--) {
  39. scanf("%d%d", &x, &y); x ^= last*p, y ^= last*p;
  40. t[x] = y, a[x] = t[x]-x, a[x+n] = t[x]-n-x;
  41. T.update(1, 1, n<<1, x), T.update(1, 1, n<<1, x+n);
  42. printf("%d\n", last = T.val[1]+n-1);
  43. }
  44. }
  45. int main() {work(); return 0; }

[HNOI 2018]转盘的更多相关文章

  1. [HNOI/AHOI2018]转盘(线段树优化单调)

    gugu  bz lei了lei了,事独流体毒瘤题 一句话题意:任选一个点开始,每个时刻向前走一步或者站着不动 问实现每一个点都在$T_i$之后被访问到的最短时间 Step 1 该题可证: 最优方案必 ...

  2. 【HNOI 2018】转盘

    Problem Description 一次小 \(G\) 和小 \(H\) 原本准备去聚餐,但由于太麻烦了于是题面简化如下: 一个转盘上有摆成一圈的 \(n\) 个物品(编号 \(1\) 至 \(n ...

  3. HNOI 2018 简要题解

    寻宝游戏 毒瘤题. 估计考试只会前30pts30pts30pts暴力然后果断走人. 正解是考虑到一个数&1\&1&1和∣0|0∣0都没有变化,&0\&0& ...

  4. [HNOI 2018]道路

    Description 题库链接 给出一棵含有 \(n\) 个叶子节点的二叉树,对于每个非叶子节点的节点,其与左儿子相连的边为公路,其与右儿子相连的边为铁路.对于每个节点,选择一条与其儿子相连的铁路或 ...

  5. [HNOI 2018]游戏

    Description 题库链接 有 \(n\) 个房间排成一列,编号为 \(1,2,...,n\) ,相邻的房间之间都有一道门.其中 \(m\) 个门上锁,其余的门都能直接打开.现在已知每把锁的钥匙 ...

  6. [HNOI 2018]排列

    Description 题库链接 给定 \(n\) 个整数 \(a_1, a_2, \dots, a_n, 0 \le ai \le n\) ,以及 \(n\) 个整数 \(w_1, w_2, \do ...

  7. 【HNOI 2018】毒瘤

    Problem Description 从前有一名毒瘤. 毒瘤最近发现了量产毒瘤题的奥秘.考虑如下类型的数据结构题:给出一个数组,要求支持若干种奇奇怪怪的修改操作(例如给一个区间内的数同时加上 \(c ...

  8. 【HNOI 2018】排列

    Problem Description 给定 \(n\) 个整数 \(a_1, a_2, \ldots , a_n(0 \le a_i \le n)\),以及 \(n\) 个整数 \(w_1, w_2 ...

  9. 【HNOI 2018】游戏

    Problem Description 一次小 \(G\) 和小 \(H\) 在玩寻宝游戏,有 \(n\) 个房间排成一列,编号为 \(1,2,-,n\),相邻房间之间都有 \(1\) 道门.其中一部 ...

随机推荐

  1. 一起学习MVC(1)初步了解MVC

    MVC 即模型视图控制器(Model View Controller)     利于团队开发.便于管理与维护.代码易读性强.未来的主流开发框架结构. 当然,缺点也显而易见,与传统开发框架相比有很大的不 ...

  2. Spring Boot 2 实践记录之 MySQL + MyBatis 配置

    如果不需要连接池,那么只需要简单的在pom文件中,添加mysql依赖: <dependency> <groupId>mysql</groupId> <arti ...

  3. SqlAlchemy操作(二)

    SQLALchemy初始化链接数据库 1. 数据库配置. https://www.cnblogs.com/mengbin0546/p/10124560.html 2.  python端操作. 一.  ...

  4. 三,mysql优化--sql语句优化之索引一

    1,需求:如何在一个项目中,找到慢查询的select,mysql数据库支持把慢查询语句,记录到日志中.供程序员分析.(默认不启用此功能,需要手动启用) 修改my.cnf文件(有些地方是my.ini) ...

  5. position:absolute元素 怎样居中

    <div style = 'height:20px;position:absolute;z-index:9999;top:0;left:0;right:0;margin:auto;'> & ...

  6. 频繁项集挖掘之Aprior和FPGrowth算法

    频繁项集挖掘的应用多出现于购物篮分析,现介绍两种频繁项集的挖掘算法Aprior和FPGrowth,用以发现购物篮中出现频率较高的购物组合. 基础知识 项:“属性-值”对.比如啤酒2罐.  项集:项的集 ...

  7. cas单点登陆系统-casServer搭建

    最近工作比较忙,空闲的时间在搞单点登陆系统,自己写了一套SSO在GitHub上,过程走通了.通过这个例子,自己熟悉了流程,而且破天荒的使用了抽象设计模式,并且熟悉了cookies和session的使用 ...

  8. 原生Js弹窗插件|web弹出层组件|对话框

    wcPop.js 是一款基于原生javascript开发的前端 web版 弹窗组件,遵循原生 H5/css3/JS 的书写规范,简单实用.拿来即用(压缩后仅10KB).已经兼容各大主流浏览器.内含多种 ...

  9. iis 如何设置http访问转向https

    把网站设置成https后,发现在浏览器输入域名后,并不能所期望的看到成功访问页面,在输入如:http://www.alipay.com后浏览器自动导航到https://www.alipay.com. ...

  10. tensorflow基础篇-2

    #-*- coding:utf-8 -*- import tensorflow as tf sess=tf.Session() #整流水线单元relu print sess.run(tf.nn.rel ...