AtCoder Regular Contest 077 E - guruguru 线性函数 前缀和
题目链接
题意
灯有\(m\)个亮度等级,\(1,2,...,m\),有两种按钮:
- 每次将亮度等级\(+1\),如\(1\rightarrow 2,2\rightarrow 3,...,m-1\rightarrow m,m\rightarrow 1\)
- 初始时有一个设定值\(x\),按下该按钮能够从任意亮度等级到达\(x\)
现给定一个序列\(a[1..n]\)代表亮度从\(a_1\rightarrow a_2\rightarrow a_3\rightarrow ... \rightarrow a_n\),问初始值\(x\)设定为多少的时候能够使总共需按按钮的次数最少?
思路
原始思路
从\(1\)到\(m\)枚举\(x\),对于每个\(x\)遍历一遍序列,计算出操作次数。
比较得到一个最小值。时间复杂度\(O(m*n)\)
本质=>优化
思考一下,上面这个思路本质上是什么?
假设我们有一个数组\(c[1..m]\)用来记录操作次数,那么其初始值为\(0\),遍历一遍序列,对每个初始值\(x\)对应的操作次数\(c[x]\)加上\(f(a_i,a_{i+1},x)\).
最后,\(c[\ ]\)数组的最小值即为答案。
再来考虑一下上面的\(f(a_i,a_{i+1},x)\),这又是什么?
记\(s=a_i,t=a_{i+1}\),不妨设\(s\lt t\)则$$f(s,t,x)=
\begin{cases}
t-s, &x\leq s\ ||\ x\gt t\cr
t-x+1, &s\lt x \leq t
\end{cases}$$
// 高兴一下,是个线性函数啊
变化量如图所示:
1 s s+1 t t+1 m
|------------|------------|------------|
( +t-s ) ( +s-x+1 )( +t-s )
仔细观察发现可以发现它可以拆成两部分
1 m
|--------------------------------------|
( +t-s )
1 s s+1 t t+1 m
|------------|------------|------------|
( +0 ) ( +t-x+1 )( +0 )
即
- 整体加上\(t-s\)
- 对\([s+1,t]\)一段加上一个递减的序列。
整体的加直接记录即可,对一段进行的修改怎么办呢?
仔细观察这个递减的序列,发现其是\({0,-1,-2,...,s-t+1}\),于是可以借助前缀和\(O(1)\)完成这个修改。
// 详见后文
于是我们的优化就完成了,成功从\(O(n*m)\)变成\(O(n)\).
附
对于\(s\gt t\)的情况,只需将\(s\)加上\(m\)考虑即可,就相当于将每个位置拆成两个。
前缀和大法
对区间\([s,t]\)中的元素分别加上\({1,2,...,n}\),要求操作后的序列,方法为:
a[s] += 1, a[t+1] -= (n+1), a[t+2] += n;
求两次前缀和即得操作后的序列。容易验证。
Code
#include <bits/stdc++.h>
#define maxn 200010
using namespace std;
typedef long long LL;
LL c[maxn], a[maxn];
int main() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 0; i < n; ++i) scanf("%lld", &a[i]);
LL base = 0;
for (int i = 1; i < n; ++i) {
LL s = a[i-1], t = a[i];
if (t < s) t += m;
base += t - s;
c[s+2] += 1, c[t+1] -= t-s, c[t+2] += t-s-1;
}
for (int i = 1; i <= (m<<1); ++i) c[i] += c[i-1];
for (int i = 1; i <= (m<<1); ++i) c[i] += c[i-1];
LL maxx = 0;
for (int i = 1; i <= m; ++i) maxx = max(maxx, c[i] + c[i+m]);
printf("%lld\n", base - maxx);
return 0;
}
AtCoder Regular Contest 077 E - guruguru 线性函数 前缀和的更多相关文章
- AtCoder Regular Contest 077 E - guruguru
https://arc077.contest.atcoder.jp/tasks/arc077_c 有m个点围成一个圈,按顺时针编号为1到m,一开始可以固定一个位置x,每次操作可以往顺时针方向走一步或直 ...
- AtCoder Regular Contest 077 被虐记&题解
直到\(7:58\)才知道今天\(8:00\)有\(AtCoder\)的菜鸡来写题解啦. C - pushpush 题目: 给定一个长为\(n\)的序列,第\(i\)次操作做如下的事 : 将\(a_i ...
- AtCoder Regular Contest 077 D - 11
题目链接:http://arc077.contest.atcoder.jp/tasks/arc077_b Time limit : 2sec / Memory limit : 256MB Score ...
- AtCoder Regular Contest 077 C - pushpush
题目链接:http://arc077.contest.atcoder.jp/tasks/arc077_a Time limit : 2sec / Memory limit : 256MB Score ...
- AtCoder Regular Contest 077
跟身在国外的Marathon-fan一起打的比赛,虽然最后没出F但还是涨分了. C - pushpush 题意:n次操作,每次往一个序列后面塞数,然后把整个序列翻转. #include<cstd ...
- 【arc077f】AtCoder Regular Contest 077 F - SS
题意 给你一个形如"SS"的串S,以及一个函数\(f(x)\),\(x\)是一个形如"SS"的字符串,\(f(x)\)也是一个形如"SS"的 ...
- AtCoder Regular Contest 096
AtCoder Regular Contest 096 C - Many Medians 题意: 有A,B两种匹萨和三种购买方案,买一个A,买一个B,买半个A和半个B,花费分别为a,b,c. 求买X个 ...
- AtCoder Regular Contest 098
AtCoder Regular Contest 098 C - Attention 题意 给定一个只包含"E","W"字符串,可以花一的花费使他们互相转换.选定 ...
- AtCoder Regular Contest 061
AtCoder Regular Contest 061 C.Many Formulas 题意 给长度不超过\(10\)且由\(0\)到\(9\)数字组成的串S. 可以在两数字间放\(+\)号. 求所有 ...
随机推荐
- 二十三、MySQL 事务
MySQL 事务 MySQL 事务主要用于处理操作量大,复杂度高的数据.比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数 ...
- 在Ubuntu下配置jdk+maven
1.在官网上下载对应Linux版本的jdk 2.在终端输入命令将下载好的jdk解压并且转移到指定的路径如:首先执行 tar -zxvf jdk-8u181-linux-x64.tar.gz 然后 ...
- awk速查手册
简介awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进 ...
- 739. Daily Temperatures
https://leetcode.com/problems/daily-temperatures/description/ class Solution { public: vector<int ...
- Sonya and Robots CodeForces - 1004C (思维题)
Sonya and Robots time limit per test 1 second memory limit per test 256 megabytes input: standard in ...
- Jin Ge Jin Qu hao UVA - 12563 01背包
题目:题目链接 思路:由于t最大值其实只有180 * 50 + 678,可以直接当成01背包来做,需要考虑的量有两个,时间和歌曲数,其中歌曲优先级大于时间,于是我们将歌曲数作为背包收益,用时间作为背包 ...
- 笔记-python-变量作用域
笔记-python-变量作用域 1. python变量作用域和引用范围 1.1. 变量作用域 一般而言程序的变量并不是任何对象或在任何位置都可以访问的,访问权限决定于这个变量是在哪里赋 ...
- Fiddler用AutoResponder实现app升级异步更新
先说一下我自己理解的异步更新:用app异步升级举例,app是否升级的检查是在启动app时访问服务器的,把app本地的最新版本号与服务器端的最新版本号做对比,假如不一致,则提示升级.但本次已经打开使用a ...
- Jconsole连接Tomcat JVM
修改java虚拟机启动参数 在%TOMCAT_HOME%\bin\catalina.sh文件的最顶端 JAVA_OPTS=”-Dcom.sun.management.jmxremote.port=10 ...
- 读书笔记jvm探秘之二: 对象创建
对象是面向对象设计语言无法回避的东西,可见其重要性,JAVA的对象相较于C++来说,不算很复杂,但是我们看到一句话背后往往有很多东西值得探讨(NEW关键字). 对象如何被创建? 首先一句简单的NEW语 ...