AtCoder:guruguru(思维 & 差分)

来源:互联网 发布:python 连接informix 编辑:程序博客网 时间:2024/05/16 04:15

E - guruguru


Time limit : 2sec / Memory limit : 256MB

Score : 700 points

Problem Statement

Snuke is buying a lamp. The light of the lamp can be adjusted to m levels of brightness, represented by integers from 1 through m, by the two buttons on the remote control.

The first button is a "forward" button. When this button is pressed, the brightness level is increased by 1, except when the brightness level is m, in which case the brightness level becomes 1.

The second button is a "favorite" button. When this button is pressed, the brightness level becomes the favorite brightness level x, which is set when the lamp is purchased.

Snuke is thinking of setting the favorite brightness level x so that he can efficiently adjust the brightness. He is planning to change the brightness n1 times. In the i-th change, the brightness level is changed from ai to ai+1. The initial brightness level is a1. Find the number of times Snuke needs to press the buttons when x is set to minimize this number.

Constraints

  • 2n,m105
  • 1aim
  • aiai+1
  • nm and ai are integers.

Input

Input is given from Standard Input in the following format:

n ma1 a2an

Output

Print the minimum number of times Snuke needs to press the buttons.


Sample Input 1

Copy
4 61 5 1 4

Sample Output 1

Copy
5

When the favorite brightness level is set to 12345 and 6, Snuke needs to press the buttons 89756 and 9 times, respectively. Thus, Snuke should set the favorite brightness level to 4. In this case, the brightness is adjusted as follows:

  • In the first change, press the favorite button once, then press the forward button once.
  • In the second change, press the forward button twice.
  • In the third change, press the favorite button once.

Sample Input 2

Copy
10 1010 9 8 7 6 5 4 3 2 1

Sample Output 2

Copy
45
题意:有个M个档的台灯,有N个目标档,需要按顺序调到相应目标档,每次只能按按钮一步一步进档,或者按一下按钮跳到x档,问x档初始化为最优档时,完成任务按的最少次数按钮。

思路:假设从a[i]到a[i+1]档,可以按a[i+1]-a[i]次,假如x设置在其中间位置,只需按a[i+1]-x+1次即可,那么可以将每个a[i]和a[i+1]看成一条线段,只要x设置在线段上,这次操作就有相应的次数减少,减少的次数为x-a[i]-1次,x在线段外即对当前操作无影响,那么b数组将线段上每个值都加上a[i]+1,同时另开数组c在同样线段上各个值+1,表示x设这个位置就能减少次数,最后遍历一下就能知道x设置在位置i能减少的总次数了,上述操作用差分数组解决,复杂度O(n)。

# include <bits/stdc++.h>using namespace std;typedef long long LL;const int maxn = 1e5;LL a[maxn+3]={0}, b[maxn+3]={0}, c[maxn+3]={0};int main(){    LL sum = 0;    int n, m;    scanf("%d%d%lld",&n,&m,&a[1]);    for(int i=2; i<=n; ++i)    {        scanf("%lld",&a[i]);        if(a[i] > a[i-1])        {            sum += a[i]-a[i-1];            b[a[i-1]+1] += a[i-1]+1;            b[a[i]+1] -= a[i-1]+1;            ++c[a[i-1]+1];            --c[a[i]+1];        }        else        {            sum += m-a[i-1]+a[i];            b[a[i-1]+1] += a[i-1]+1;            ++c[a[i-1]+1];            b[1] -= m-a[i-1]-1;            ++c[1];            b[a[i]+1] += m-a[i-1]-1;            --c[a[i]+1];        }    }    for(int i=1; i<=m; ++i)        b[i] += b[i-1], c[i] += c[i-1];    LL ans = 0;    for(int i=1; i<=m; ++i)        ans = max(ans,i*1LL*c[i]-b[i]);    printf("%lld\n",sum-ans);    return 0;}


原创粉丝点击