「HNOI2018」转盘
「HNOI2018」转盘
现场推出了大部分结论但是只写了 \(40\) 分暴力,被贺指导踩爆,现在还有点怀念 HNOI2018 贺指导对着镜子荒野行动的日子,那几天他云球迷瞎**指点篮球,被送上指导称号一个。
解题思路:
可以大力证明一定存在一种最优解只需要走一圈,假设存在一个最优解在某个时刻已经走了一圈回到出发点还剩下一些点没有被标记,那么最终还需要走到这些点标记一遍,这样的时间开销和在需要被标记的点之前等到它可以再走是等价的,所以一定存在一种最优解是在起始点等若干时刻然后一遍走完的。
于是可以把环倍长为 \(T_1,T_2\dots T_{2n}\) ,枚举一个起始点 \(1\leq s \leq n\) ,贡献就是
\\ ans = n-1+\min_{1\leq s \leq n}(s+\max_{s\leq i < s+n} (T_i-i))
\]
这个东西是所有长度为 \(n\) 的区间的贡献的 \(\min\) ,不太好维护,观察发现每一个区间后面的元素必然会小于区间内元素的 \(\max\) ,因为后面的元素都是倍长后没有被用到的 \(T_{i+n}\) ,显然 \(T_{i+n}-i-n<T_i-i\) 。
于是问题就转化为对于每一个后缀算贡献取 \(\min\) ,经典线段树维护单调栈求解即可。
具体来说,令 \(Ans(l,r)\) 为左端点在 \([l,mid]\) 的所有后缀贡献的 \(\min\) ,再维护一下区间 \(\max\) ,那么可以线段树二分找到 \(\max[mid+1,r]\) 在 \([l,mid]\) 中的位置 \(pos\) ,那么 \(pos\) 及以后的贡献是 \(pos+\max[mid+1,r]\) ,\(pos\) 之前的贡献就是那个节点原先的 \(Ans\) 。
这样搞一搞更新需要额外的一个 \(\log\) ,总时间复杂度 \(\mathcal O(n\log^2n)\) 。
code
/*program by mangoyang*/
#pragma GCC optimize("O2", "Ofast")
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int ch = 0, f = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
const int N = 200005;
int t[N], n, m, p;
namespace Seg{
#define lson (u << 1)
#define rson (u << 1 | 1)
#define mid ((l + r) >> 1)
int mx[N<<2], s[N<<2];
inline int find(int u, int l, int r, int x){
if(l == r) return l + max(mx[u], x);
if(mx[rson] >= x)
return min(s[u], find(rson, mid + 1, r, x));
return min(mid + 1 + x, find(lson, l, mid, x));
}
inline void update(int u, int l, int r){
mx[u] = max(mx[lson], mx[rson]);
s[u] = find(lson, l, mid, mx[rson]);
}
inline void build(int u, int l, int r){
if(l == r) return (void) (mx[u] = t[l], s[u] = l + t[l]);
build(lson, l, mid), build(rson, mid + 1, r);
update(u, l, r);
}
inline void modify(int u, int l, int r, int pos, int x){
if(l == r) return (void) (mx[u] = x, s[u] = l + x);
if(pos <= mid) modify(lson, l, mid, pos, x);
else modify(rson, mid + 1, r, pos, x);
update(u, l, r);
}
}
int main(){
read(n), read(m), read(p);
for(int i = 1; i <= n; i++) read(t[i]);
for(int i = 1; i <= n; i++) t[i+n] = t[i];
for(int i = 1; i <= 2 * n; i++) t[i] -= i;
Seg::build(1, 1, 2 * n);
int lastans = Seg::s[1] + n - 1;
printf("%d\n", lastans);
for(int i = 1, x, y; i <= m; i++){
read(x), read(y), x ^= lastans * p, y ^= lastans * p;
Seg::modify(1, 1, 2 * n, x, y - x);
Seg::modify(1, 1, 2 * n, x + n, y - x - n);
printf("%d\n", lastans = Seg::s[1] + n - 1);
}
return 0;
}
「HNOI2018」转盘的更多相关文章
- Loj #2495. 「AHOI / HNOI2018」转盘
Loj #2495. 「AHOI / HNOI2018」转盘 题目描述 一次小 G 和小 H 原本准备去聚餐,但由于太麻烦了于是题面简化如下: 一个转盘上有摆成一圈的 \(n\) 个物品(编号 \(1 ...
- 「AHOI / HNOI2018」转盘 解题报告
「AHOI / HNOI2018」转盘 可能是我语文水平不太行... 首先可以猜到一些事实,这个策略一定可以被一个式子表示出来,不然带修修改个锤子. 然后我们发现,可以枚举起点,然后直接往前走,如果要 ...
- 「HNOI2018」毒瘤
「HNOI2018」毒瘤 解题思路 先考虑只有一棵树的情况,经典独立集计数. \[ dp[u][0]=\prod (dp[v][0]+dp[v][1]) \\ dp[u][1]=\prod dp[v] ...
- 「HNOI2018」游戏
「HNOI2018」游戏 解题思路 首先没有锁上的门可以缩点缩掉,然后对于一扇锁上的门,如果钥匙在左边,那么右边就永远不可能到达左边,同理如果钥匙在右边,左边就永远不可能到达右边. 然后考虑一个暴力的 ...
- 【LOJ】#2495. 「AHOI / HNOI2018」转盘
题面 题解 考虑我肯定是从一个人出发,开始依次标记,而不会跳过某个人,因为如果我跳过了,那么我之后回来还需要标记它,比不上我等完它再一直走到最后(因为多了走一圈之后走回它的代价) 我们倍长整个序列,我 ...
- Loj #2494. 「AHOI / HNOI2018」寻宝游戏
Loj #2494. 「AHOI / HNOI2018」寻宝游戏 题目描述 某大学每年都会有一次 Mystery Hunt 的活动,玩家需要根据设置的线索解谜,找到宝藏的位置,前一年获胜的队伍可以获得 ...
- loj #2510. 「AHOI / HNOI2018」道路
#2510. 「AHOI / HNOI2018」道路 题目描述 W 国的交通呈一棵树的形状.W 国一共有 n−1 个城市和 nnn 个乡村,其中城市从 111 到 n−1 编号,乡村从 111 到 n ...
- loj #2509. 「AHOI / HNOI2018」排列
#2509. 「AHOI / HNOI2018」排列 题目描述 给定 nnn 个整数 a1,a2,…,an(0≤ai≤n),以及 nnn 个整数 w1,w2,…,wn.称 a1,a2,…,an 的 ...
- loj #2508. 「AHOI / HNOI2018」游戏
#2508. 「AHOI / HNOI2018」游戏 题目描述 一次小 G 和小 H 在玩寻宝游戏,有 nnn 个房间排成一列,编号为 1,2,…,n,相邻房间之间都有 111 道门.其中一部分门上有 ...
随机推荐
- Go语言的各种Print函数
Go语言的各种Print函数 func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) func Pr ...
- 20155303 2016-2017-2 《Java程序设计》第九周学习总结
20155303 2016-2017-2 <Java程序设计>第九周学习总结 目录 学习内容总结(Linux命令) 教材学习中的问题和解决过程 代码调试中的问题和解决过程 代码托管 上周考 ...
- Spring4笔记7--AspectJ 对 AOP 的实现
AspectJ 对 AOP 的实现: 对于 AOP 这种编程思想,很多框架都进行了实现.Spring 就是其中之一,可以完成面向切面编程.然而,AspectJ 也实现了 AOP 的功能,且其实现方式更 ...
- accept系统调用
/* * For accept, we attempt to create a new socket, set up the link * with the client, wake up the c ...
- 试用Redis
Windows 10家庭中文版,运行于VirtualBox上的Ubuntu 18.04,Redis 4.0.10, Redis,久仰大名!因为没有从事互联网行业,所以一直没有使用过.近期找工作,也隐约 ...
- android设备休眠
从上面的连接里面找到了一些资料: 如果一开始就对Android手机的硬件架构有一定的了解,设计出的应用程序通常不会成为待机电池杀手,而要设计出正确的通信机制与通信协议也并不困难.但如果不去了解而盲目设 ...
- OBJECT_ID()的使用方法
数据库中每个对像都有一个唯一的ID值,用Object_name(id)可以根据ID值得到对像的名称,object_id(name)可以根据对像名称得到对象的ID object_id()只能返回用户创建 ...
- bzoj 4034(DFS序+线段树)
这个题多了一个操作难度直线上升,看完题解才会写 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 ...
- java正则表达式(转)
1.验证email public static void main(String[] args) { // 要验证的字符串 String str = "service@xsoftlab.ne ...
- 搜索入门之dfs--经典的迷宫问题解析
今天来谈一下dfs的入门,以前看到的dfs入门,那真的是入门吗,都是把dfs的实现步骤往那一贴,看完是知道dfs的步骤了,但是对于代码实现还是没有概念.今天准备写点自己的心得,真的是字面意思--入门. ...