【题解】HNOI2018转盘
何学长口中所说的‘一眼题’……然而实际上出出来我大HN全省也只有一个人A……
首先我们需要发现一个性质:我们永远可以在最后一圈去标记所有的物品。倘若我们反复转圈,那么这完全是可以省下来的。所以我们破环为链,以\(S\) 物品作为第一个被访问的节点时所需要的时间就是 \( max(T_{x} - x) + S \),其中 \( S <= x <= S + n - 1\)。问题转化为如何使用数据结构来维护这些值得最小值。注意到 \(T_{x} - x \)都只与 \(x\) 有关,我们就他将它们合为一个变量 :\(A_{x} = T_{x} - x\)。由于 \(T_{x} == T_{x + n}\),所以 \(A_{x} > A_{x +n}\) 。所以若 \(A_{x} = max(A_{j}) (S <= j <= S + n - 1)\),那么 \(A_{x} = max(A_{j}) (S <= j <= 2 * n)\)。这里应该是一个启示吧,有时候观察数组的性质,不仅仅缩小范围是有效的,实际上扩大范围为前缀 / 后缀也一样是非常重要的一个方面。那么这个时候我们就发现:这实际上对于答案可能产生贡献的就是所有从后往前比任何一个元素都要大的 \(A_{x}\) 啦。
使用线段树我们可以维护这样的一个单调栈,由于我们已经固定了 \(A_{x}\),我们只需要使得 \(S\) 最小即可。显然\(S\)尽量小就应该是 \(x\) 左侧第一个比它大的数的下标+1。使用线段树维护这个信息的最大值即可(楼房重建问题)。
其中 \(mx\) 维护区间内 \(A_{x}\) 的最大值,\(mn\) 维护区间内 \(A_{x} + S\) 的最小值, \(rec\) 记录区间内只考虑左边区间 & 右边区间最大值的贡献 (但考虑右边对于左边的限制) 。
#include <bits/stdc++.h>
using namespace std;
#define maxn 1000000
#define INF 999999999
int n, m, P, N, ans, T[maxn];
int mn[maxn], mx[maxn], rec[maxn]; int read()
{
int x = , k = ;
char c; c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} int Query(int p, int l, int r, int K)
{
if(l == r)
{
if(mx[p] > K) return min(mn[p], K + l + );
else return INF;
}
int mid = (l + r) >> ;
if(mx[p << | ] <= K) return Query(p << , l, mid, K);
else return min(rec[p], Query(p << | , mid + , r, K));
} void Push_Up(int p, int l, int r)
{
int ls = p << , rs = p << | ;
mx[p] = max(mx[ls], mx[rs]);
int mid = (l + r) >> ;
mn[p] = min(rec[p] = Query(ls, l, mid, mx[rs]), mn[p << | ]);
} void Build(int p, int l, int r)
{
if(l == r)
{
mx[p] = T[l] - l; mn[p] = T[l];
return;
}
int mid = (l + r) >> ;
Build(p << , l, mid); Build(p << | , mid + , r);
Push_Up(p, l, r);
} void Update(int p, int l, int r, int x)
{
if(l == r)
{
mx[p] = T[l] - l; mn[p] = T[l];
return;
}
int mid = (l + r) >> ;
if(x <= mid) Update(p << , l, mid, x);
else Update(p << | , mid + , r, x);
Push_Up(p, l, r);
} int main()
{
n = read(), m = read(), P = read(), N = * n;
for(int i = ; i <= n; i ++) T[i] = read();
for(int i = ; i <= n; i ++) T[i + n] = T[i];
Build(, , N);
printf("%d\n", ans = min(mx[] + , rec[]) + n - );
for(int i = ; i <= m; i ++)
{
int x = read(), y = read();
if(P) x ^= ans, y ^= ans;
T[x] = T[x + n] = y;
Update(, , N, x); Update(, , N, x + n);
printf("%d\n", ans = min(mx[] + , rec[]) + n - );
}
return ;
}
【题解】HNOI2018转盘的更多相关文章
- 【BZOJ5286】[HNOI2018]转盘(线段树)
[BZOJ5286][HNOI2018]转盘(线段树) 题面 BZOJ 洛谷 题解 很妙的一道题目啊.(全世界除了我这题都有40分,就我是一个状压选手 首先来发现一些性质,我们走一圈一定不会更差. 为 ...
- 5286: [Hnoi2018]转盘
5286: [Hnoi2018]转盘 链接 分析: $\min\limits_{i=1}^n \{ \max\limits_{j=i}^{i + n - 1} \{ a_{j}+i \} \} +n- ...
- [HNOI2018]转盘
[HNOI2018]转盘 给你一个 \(n\) 元环, 你可以在 \(0\) 时刻从任意一个位置出发, 每一秒可以选择往后或者留在原地每个点有个参数 \(T_i\) , 当你走到 \(i\) 的时间 ...
- [BZOJ5286][洛谷P4425][HNOI2018]转盘(线段树)
5286: [Hnoi2018]转盘 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 15 Solved: 11[Submit][Status][Di ...
- BZOJ5286: [Hnoi2018]转盘 (线段树)
题意 给你绕成一圈的物品共 \(n\) 个 , 然后从其中一个开始选 , 每次有两种操作 , 一是继续选择当前物品 , 二是选择这个后一个物品 . 选择后一个物品要求当前的时刻大于后一个的 \(T_i ...
- bzoj5286 [Hnoi2018]转盘
题目描述: bz luogu 题解: 看了半个晚上终于明白了. 首先最优决策一定有:在起始点停留一段时间然后一直前进. 解释网上有很多,在这里不赘述了. (由于是环,先把$T$数组倍长.) 首先基于决 ...
- bzoj 5286: [Hnoi2018]转盘
Description Solution 首先注意到一个点不会走两次,只会有停下来等待的情况,把序列倍长 那么如果枚举一个起点\(i\),答案就是 \(min(max(T[j]+n-(j-i)-1)) ...
- BZOJ.5286.[AHOI/HNOI2018]转盘(线段树)
BZOJ LOJ 洛谷 如果从\(1\)开始,把每个时间\(t_i\)减去\(i\),答案取决于\(\max\{t_i-i\}\).记取得最大值的位置是\(p\),答案是\(t_p+1+n-1-p=\ ...
- [HNOI2018]转盘[结论+线段树]
题意 题目链接 分析 首先要发现一个结论:最优决策一定存在一种 先在出发点停留之后走一圈 的情况,可以考虑如下证明: 如果要停留的话一定在出发点停留,这样后面的位置更容易取到. 走超过两圈的情况都可以 ...
随机推荐
- Java编辑环境搭建
1.Java开发环境搭建 这里主要说的是在Windows系统下的环境搭建 JDK的安装 java的sdk简称JDK ,去其官方网站下载最近的JDK即可http://www.oracle.com/tec ...
- VINS(五)非线性优化与在线标定调整
首先根据最大后验估计(Maximum a posteriori estimation,MAP)构建非线性优化的目标函数. 初始化过程通过线性求解直接会给出一个状态的初值,而非线性优化的过程关键在于求解 ...
- 回写盘写速度被限速为10M左右
问题现像如下图所示: 用hd-speed等测试虚拟盘速度都能达到90M/s左右,但复制文件到虚拟盘速度最高只有10M/s 原因:由于客户机开机加载这个随机驱动和随机进程后,会对磁盘启动进程等有扫描检查 ...
- json模块使用总结——Python
# 原创文章,未经允许请勿转载 通过Python的json模块,可以将字符串形式的json数据转化为字典,也可以将Python中的字典数据转化为字符串形式的json数据. 之前使用这个模块时,都是随用 ...
- html div内第二行文字显示不下的时候才用省略号代替 css实现
有时候文字太多,但为了美观想要在第二行的时候才显示省略号,而不是第一行超出马上就出现省略号 下面是css代码: overflow:hidden;text-overflow: ellipsis;//显示 ...
- 各种对list,string操作函数的总结
#encoding=utf-8#reverse,用来反转lista=['aa','bb','cc']a.reverse()print a#['cc', 'bb', 'aa']#不能直接print a. ...
- gitignore 文件生效办法
.gitignore 可以添加一些不加入git版本控制的文件 比如一些测试文件.因人而异的配置信息等等 .gitignore 文件展示如下 /.idea/target//.classpath /.pr ...
- 深入理解 Vuejs 动画效果
本文主要归纳在 Vuejs 学习过程中对于 Vuejs 动画效果的各个相关要点.由于本人水平有限,如文中出现错误请多多包涵并指正,感谢.如果需要看更清晰的代码高亮,请跳转至我的个人站点的 深入理解 V ...
- kafka stream 低级别的Processor API动态生成拓扑图
public class KafkaSream { public static void main(String[] args) { Map<String, Object> props = ...
- 完全背包问题 :背包dp
题目描述: 有 N种物品和一个容量是 V 的背包,每种物品都有无限件可用.第 i 种物品的体积是 vi,价值是 wi. 求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大.输出最 ...