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

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+5; int n, m, p, t[N], a[N], x, y, last;
struct Segment_tree {
#define lr(o) (o<<1)
#define rr(o) (o<<1|1)
int maxn[N<<2], val[N<<2];
int query(int o, int l, int r, int mx) {
if (l == r) return l+max(mx, maxn[o]); int mid = (l+r)>>1;
if (mx <= maxn[rr(o)]) return min(val[o], query(rr(o), mid+1, r, mx));
else return min(mid+mx+1, query(lr(o), l, mid, mx));
}
void pushup(int o, int l, int mid, int r) {
val[o] = query(lr(o), l, mid, maxn[rr(o)]);
maxn[o] = max(maxn[lr(o)], maxn[rr(o)]);
}
void build(int o, int l, int r) {
if (l == r) {maxn[o] = a[l], val[o] = l+a[l]; return; }
int mid = (l+r)>>1;
build(lr(o), l, mid), build(rr(o), mid+1, r);
pushup(o, l, mid, r);
}
void update(int o, int l, int r, int loc) {
if (l == r) {maxn[o] = a[l], val[o] = l+a[l]; return; }
int mid = (l+r)>>1;
if (loc <= mid) update(lr(o), l, mid, loc);
else update(rr(o), mid+1, r, loc);
pushup(o, l, mid, r);
}
}T; void work() {
scanf("%d%d%d", &n, &m, &p);
for (int i = 1; i <= n; i++)
scanf("%d", &t[i]), a[i] = t[i]-i, a[i+n] = t[i]-n-i;
T.build(1, 1, n<<1);
printf("%d\n", last = T.val[1]+n-1);
while (m--) {
scanf("%d%d", &x, &y); x ^= last*p, y ^= last*p;
t[x] = y, a[x] = t[x]-x, a[x+n] = t[x]-n-x;
T.update(1, 1, n<<1, x), T.update(1, 1, n<<1, x+n);
printf("%d\n", last = T.val[1]+n-1);
}
}
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. gdb用法

    mickole@test:~/ctest/05gdb$ gdb simple //开始gdb调试 GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4- ...

  2. Caliburn.Micro(MVVM框架)

    一.首启窗体设置 1. 创建一个新的WPF应用程序并添加NuGet包:Caliburn.Micro 2. 删除项目自带的主窗口文件MainWindow.xaml 3. 在App.xaml项目文件中,删 ...

  3. SqlAlchemy操作(一)

    博客转载于 http://www.cnblogs.com/haiyan123/p/8270520.html 一. 介绍 SQLAlchemy是一个基于Python实现的ORM框架.该框架建立在 DB ...

  4. Android 美学设计基础 <3>

    本期接着对Android的美学设计的分享. 1.3 Light and shadows 光学与阴影 1.3.1 Light 在素材设计的环境中,我们会用虚拟的光来照亮UI界面.主灯光会产生尖锐,有方向 ...

  5. Flask从入门到精通之使用Flask-Migrate实现数据库迁移

    在开发程序的过程中,你会发现有时需要修改数据库模型,而且修改之后还需要更新数据库.仅当数据库表不存在时,Flask-SQLAlchemy 才会根据模型进行创建.因此,更新表的唯一方式就是先删除旧表,不 ...

  6. java保留小数点两位的4种方法

    import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.NumberFormat; public c ...

  7. iOS开发总结--三方平台开发之分享

    1.前言 在公司参与了多个应用三方平台的开发,涉及微信.微博.QQ.Facebook.meetup等,总结一下一般的接入三方平台SDK方法. 2.接入三方SDK 任何应用要接入三方平台,都需要在该平台 ...

  8. css单行文本及多行文本溢出显示省略号

    关于文本溢出的相关属性: 1. text-overflow: clip|ellipsis|string;   该属性规定当文本溢出包含元素时发生的事情. clip : 修剪文本. ellipsis : ...

  9. hbase搭建web项目 报500错误 HTTP Status 500 - Unable to compile class for JSP

    在昨天,用hbase做后台搭建web项目时,前边的进行的非常顺利,当运行时便 报错了,截图如下: 这是直接在jsp中接收参数报的错误,如果在servlet中,同样也是报500的错误,虽然显示的不太一样 ...

  10. 【hdu6035】 Colorful Tree dfs序

    题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题目大意:给你一棵树,树上每个节点都有一个颜色. 现在定义两点间的距离为两点最短路径上颜色集合 ...