题目链接

题意

灯有\(m\)个亮度等级,\(1,2,...,m\),有两种按钮:

  1. 每次将亮度等级\(+1\),如\(1\rightarrow 2,2\rightarrow 3,...,m-1\rightarrow m,m\rightarrow 1\)
  2. 初始时有一个设定值\(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 )

  1. 整体加上\(t-s\)
  2. 对\([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 线性函数 前缀和的更多相关文章

  1. AtCoder Regular Contest 077 E - guruguru

    https://arc077.contest.atcoder.jp/tasks/arc077_c 有m个点围成一个圈,按顺时针编号为1到m,一开始可以固定一个位置x,每次操作可以往顺时针方向走一步或直 ...

  2. AtCoder Regular Contest 077 被虐记&题解

    直到\(7:58\)才知道今天\(8:00\)有\(AtCoder\)的菜鸡来写题解啦. C - pushpush 题目: 给定一个长为\(n\)的序列,第\(i\)次操作做如下的事 : 将\(a_i ...

  3. AtCoder Regular Contest 077 D - 11

    题目链接:http://arc077.contest.atcoder.jp/tasks/arc077_b Time limit : 2sec / Memory limit : 256MB Score ...

  4. AtCoder Regular Contest 077 C - pushpush

    题目链接:http://arc077.contest.atcoder.jp/tasks/arc077_a Time limit : 2sec / Memory limit : 256MB Score ...

  5. AtCoder Regular Contest 077

    跟身在国外的Marathon-fan一起打的比赛,虽然最后没出F但还是涨分了. C - pushpush 题意:n次操作,每次往一个序列后面塞数,然后把整个序列翻转. #include<cstd ...

  6. 【arc077f】AtCoder Regular Contest 077 F - SS

    题意 给你一个形如"SS"的串S,以及一个函数\(f(x)\),\(x\)是一个形如"SS"的字符串,\(f(x)\)也是一个形如"SS"的 ...

  7. AtCoder Regular Contest 096

    AtCoder Regular Contest 096 C - Many Medians 题意: 有A,B两种匹萨和三种购买方案,买一个A,买一个B,买半个A和半个B,花费分别为a,b,c. 求买X个 ...

  8. AtCoder Regular Contest 098

    AtCoder Regular Contest 098 C - Attention 题意 给定一个只包含"E","W"字符串,可以花一的花费使他们互相转换.选定 ...

  9. AtCoder Regular Contest 061

    AtCoder Regular Contest 061 C.Many Formulas 题意 给长度不超过\(10\)且由\(0\)到\(9\)数字组成的串S. 可以在两数字间放\(+\)号. 求所有 ...

随机推荐

  1. 自动化运维工具——ansible模板与roles(四)

    一. 模板Templates 文本文件,嵌套有脚本(使用模板编程语言编写) Jinja2语言,使用字面量,有下面形式 字符串:使用单引号或双引号 数字:整数,浮点数 列表:[item1, item2, ...

  2. CMD终端关于pip报错,scrapy报错的一种处理方法

    CMD终端关于pip报错,scrapy报错的一种处理方法 如果在终端输入pip,或scrapy,报如下错误: Fatal error in launcher: Unable to create pro ...

  3. stm32串口——标志位学习

    /* 在USART的发送端有2个寄存器,一个是程序可以看到的USART_DR寄存器,另一个是程序看不到的移位寄存器,对应USART数据发送有两个标志,一个是TXE=发送数据寄存器空,另一个是TC=发送 ...

  4. 记忆化搜索:HDU1078-FatMouse and Cheese(记忆化搜索)

    FatMouse and Cheese Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...

  5. n个人排队都不站在原来的位置

    一.题目描述 有n个人首先站成一排,请问,当n个人第二次再重新排列,每个人都不在原来的位置上,问有多少种站法.例如,原来有3个人,ABC,那么第二次每个人都不在原来的位置上有2种站法,BCA和CAB, ...

  6. Diycode开源项目 Glide图片加载分析

    1.使用Glide前的准备 1.1.首先要build.gradle中添加   github原地址点击我. 参考博客:Glide-开始! 参考博客:android图片加载库Glide的使用介绍. 参考博 ...

  7. 3 ways of including JavaScript in HTML

    Code written in JavaScript must be executed from a document written in HTML. There are three ways of ...

  8. django 自定义过滤器中的坑.

    今天在创建自定义过滤器的时候,设置已正常.但是在运行后报: 'filter' is not a valid tag library: Template library filter not found ...

  9. MD5碰撞

    if ( $_POST['param1'] !==$_POST['param2'] && md5($_POST['param1']) === md5($_POST['param2']) ...

  10. ROM+VGA 图片显示

    内容 1.将一幅图片制成mif文件,初始化rom,图片像素为 120 * 60 2.驱动VGA,将图片显示在屏幕上 1.VGA 时序 下面是我的笔记截图,感觉更好理解. 2.640*480 60hz ...