[HNOI 2018]转盘
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]转盘的更多相关文章
- [HNOI/AHOI2018]转盘(线段树优化单调)
gugu bz lei了lei了,事独流体毒瘤题 一句话题意:任选一个点开始,每个时刻向前走一步或者站着不动 问实现每一个点都在$T_i$之后被访问到的最短时间 Step 1 该题可证: 最优方案必 ...
- 【HNOI 2018】转盘
Problem Description 一次小 \(G\) 和小 \(H\) 原本准备去聚餐,但由于太麻烦了于是题面简化如下: 一个转盘上有摆成一圈的 \(n\) 个物品(编号 \(1\) 至 \(n ...
- HNOI 2018 简要题解
寻宝游戏 毒瘤题. 估计考试只会前30pts30pts30pts暴力然后果断走人. 正解是考虑到一个数&1\&1&1和∣0|0∣0都没有变化,&0\&0& ...
- [HNOI 2018]道路
Description 题库链接 给出一棵含有 \(n\) 个叶子节点的二叉树,对于每个非叶子节点的节点,其与左儿子相连的边为公路,其与右儿子相连的边为铁路.对于每个节点,选择一条与其儿子相连的铁路或 ...
- [HNOI 2018]游戏
Description 题库链接 有 \(n\) 个房间排成一列,编号为 \(1,2,...,n\) ,相邻的房间之间都有一道门.其中 \(m\) 个门上锁,其余的门都能直接打开.现在已知每把锁的钥匙 ...
- [HNOI 2018]排列
Description 题库链接 给定 \(n\) 个整数 \(a_1, a_2, \dots, a_n, 0 \le ai \le n\) ,以及 \(n\) 个整数 \(w_1, w_2, \do ...
- 【HNOI 2018】毒瘤
Problem Description 从前有一名毒瘤. 毒瘤最近发现了量产毒瘤题的奥秘.考虑如下类型的数据结构题:给出一个数组,要求支持若干种奇奇怪怪的修改操作(例如给一个区间内的数同时加上 \(c ...
- 【HNOI 2018】排列
Problem Description 给定 \(n\) 个整数 \(a_1, a_2, \ldots , a_n(0 \le a_i \le n)\),以及 \(n\) 个整数 \(w_1, w_2 ...
- 【HNOI 2018】游戏
Problem Description 一次小 \(G\) 和小 \(H\) 在玩寻宝游戏,有 \(n\) 个房间排成一列,编号为 \(1,2,-,n\),相邻房间之间都有 \(1\) 道门.其中一部 ...
随机推荐
- AndroidPn消息推送
接着前面的工作,消息接收之后,要推送给不同的客户端.关于消息推送,网上有很多方式,http长连接,xmpp协议,还有一个谷歌的貌似叫C2DM的东西. 在此之前,用openfire做了一个小demo,例 ...
- linux系统编程之进程(七):system()函数使用
一,system()理解 功能:system()函数调用"/bin/sh -c command"执行特定的命令,阻塞当前进程直到command命令执行完毕 原型: int syst ...
- 【Kindeditor编辑器】 文件上传、空间管理
包括图片上传.文件上传.Flash上传.多媒体上传.空间管理(图片空间.文件空间等等) 一.编辑器相关参数 二.简单的封装类 这里只是做了简单的封装,欢迎大家指点改正. public class Ki ...
- .NET Entity Framework (with Oracle ODP.NET)
一.前言 1.Entity Framework是什么? Entity Framework是微软对ORM框架的实现.类似的实现也有其它方式,如DevExpress 的XPO(eXpress Persis ...
- 使用libxml2进行xml开发(一)
(一)Windows下使用MinGW和Code::Blocks环境配置libxml2 笔者此次是在windows 7下使用MinGW和Code::Blocks开发C程式的,手上的一个项目需要使用soc ...
- docker 下载加速
执行这个命令: curl -SSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud. ...
- 什么是Ajax?Ajax的原理是什么?Ajax的核心技术是什么?Ajax的优缺点是什么?
Ajax是一种无需重新加载整个网页,能够更新部分网页的技术.Asynchronous JavaScript and XML的缩写,是JavaScript.XML.CSS.DOM等多个技术的组合. Aj ...
- Web安全学习图径——系列课程推荐
本文作者:i春秋作家 大哥哥团长 说到Web安全必须要了解Web方面的一些基础知识做为铺垫的去的去学习这门技术,因为不是人人都可以直接先渗透在进行编程等方面学习的.所以为了更好的入门的Web安全必须要 ...
- 【mongodb】——常用命令大全
MongoDB是NoSQL数据库系统中比较流行的数据库之一.它也是最接近关系型数据库的,一个数据库可以包含多个集合(Collection),类似于关系数据库中的表:而每个集合中可以存储一组由列标识的记 ...
- iOS多线程---NSOperation的常用操作
1.最大并发数: - (NSInteger)maxConcurrentOperationCount;- (void)setMaxConcurrentOperationCount:(NSInteger) ...