B. Suffix Operations

[Codeforces Round #688 (Div. 2)]

B. Suffix Operations

1、原题

B. Suffix Operations
time limit per test
1 second
memory limit per test
512 megabytes
input
standard input
output
standard output

Gildong has an interesting machine that has an array aa with nn integers. The machine supports two kinds of operations:

  1. Increase all elements of a suffix of the array by 11.
  2. Decrease all elements of a suffix of the array by 11.
    A suffix is a subsegment (contiguous elements) of the array that contains anan. In other words, for all ii where aiai is included in the subsegment, all ajaj’s where i<j≤ni<j≤n must also be included in the subsegment.
    Gildong wants to make all elements of aa equal — he will always do so using the minimum number of operations necessary. To make his life even easier, before Gildong starts using the machine, you have the option of changing one of the integers in the array to any other integer. You are allowed to leave the array unchanged. You want to minimize the number of operations Gildong performs. With your help, what is the minimum number of operations Gildong will perform?
    Note that even if you change one of the integers in the array, you should not count that as one of the operations because Gildong did not perform it.
    Input
    Each test contains one or more test cases. The first line contains the number of test cases tt (1≤t≤10001≤t≤1000).
    Each test case contains two lines. The first line of each test case consists of an integer nn (2≤n≤2⋅1052≤n≤2⋅105) — the number of elements of the array aa.
    The second line of each test case contains nn integers. The ii-th integer is aiai (−5⋅108≤ai≤5⋅108−5⋅108≤ai≤5⋅108).
    It is guaranteed that the sum of nn in all test cases does not exceed 2⋅1052⋅105.
    Output
    For each test case, print one integer — the minimum number of operations Gildong has to perform in order to make all elements of the array equal.
    Example

input

7
2
1 1
3
-1 0 2
4
99 96 97 95
4
-3 -5 -2 1
6
1 4 3 2 4 1
5
5 0 0 0 5
9
-367741579 319422997 -415264583 -125558838 -300860379 420848004 294512916 -383235489 425814447

output

0
1
3
4
6
5
2847372102

Note
    In the first case, all elements of the array are already equal. Therefore, we do not change any integer and Gildong will perform zero operations.
In the second case, we can set a3a3 to be 00, so that the array becomes [−1,0,0][−1,0,0]. Now Gildong can use the 22-nd operation once on the suffix starting at a2a2, which means a2a2 and a3a3 are decreased by 11, making all elements of the array −1−1.
In the third case, we can set a1a1 to 9696, so that the array becomes [96,96,97,95][96,96,97,95]. Now Gildong needs to:
• Use the 22-nd operation on the suffix starting at a3a3 once, making the array [96,96,96,94][96,96,96,94].
• Use the 11-st operation on the suffix starting at a4a4 22 times, making the array [96,96,96,96][96,96,96,96].
In the fourth case, we can change the array into [−3,−3,−2,1][−3,−3,−2,1]. Now Gildong needs to:
• Use the 22-nd operation on the suffix starting at a4a4 33 times, making the array [−3,−3,−2,−2][−3,−3,−2,−2].
• Use the 22-nd operation on the suffix starting at a3a3 once, making the array [−3,−3,−3,−3][−3,−3,−3,−3].

1、题意

    非常简单,就是给你一个序列,你可以先改变一个任意元素的值,然后对这个序列后任意个元素进行加一或减一操作,直到所有元素都相等,问最小的操作次数。

2、思路

1. 贪心确定序列最终值

         首先我们要确定的是这个序列操作后所有元素一定等于第一个元素(当第一个元素没被删除时)或者第二个元素(第一个元素被删除了)的值,非常容易想到,如果我们改动序列中第一个元素的值,我们后面所有的元素都会同时变动,这相当于做了无用功。

2. 更改元素等同于删除元素

          如果我们要更改一个元素,我们肯定会先令在所有影响这个元素的操作执行后刚好等于序列最终值,这就相当于这个元素不存在一样,在这里更改和删除是等价的。

3.dp状态机an[n+2][2][2]

攻克了我们要把元素变为多少,下面的操作就是一个普通的状态机。
我的代码使用了an[x][y][z]表示其状态,其中x代表现在在操作第几个元素,y代表包括这个元素在内是否有被更改过,z表示如果更改的话更改的是否是当前元素。

注意:an[x][1][0]于an[x][0][1]是没有意义的。
下面就是状态转移方程了,

1、 如果这个元素和这个元素之前的元素都没有改变an[x][0][0]

        就等于上一个元素和上一个元素之前的元素都不改变的值加上当前元素和前一个元素只差的绝对值。

an[x][0][0]=an[x-1][0][0]+abs(s[x]-s[x-1])

2、如果这个元素之前的元素有改变 an[x][1][0]

这里不象上一个只有一个状态能转移到这个位置,能转移到这个状态的状态有两个删除前一个元素和删除前一个元素之前的元素
和上一个状态相同,我们只要加上当前元素和前一个元素只差的绝对值(删除前一个元素之前的元素)或加上当前元素和前一个元素的前一个元素只差的绝对值(删除前一个元素)取两者的最小值
a n [ x ] [ 1 ] [ 0 ] = m i n ( a n [ x − 1 ] [ 1 ] [ 0 ] + a b s ( s [ x ] − s [ x − 1 ] ) , a n [ x − 1 ] [ 1 ] [ 1 ] + a b s ( s [ x ] − s [ x − 2 ] ) ) an[x][1][0]=min(an[x-1][1][0]+abs(s[x]-s[x-1]), an[x-1][1][1]+abs(s[x]-s[x-2])) an[x][1][0]=min(an[x1][1][0]+abs(s[x]s[x1]),an[x1][1][1]+abs(s[x]s[x2]))

3、 如果改变当前元素an[x][1][1]

这个非常简单,改变当前元素就相当于没有这个元素,操作数和前一个元素没有改动过的操作次数相同
an[x][1][1]= an[x-1][0][0]

3.代码

话不多说,show your code.

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
long long abbs(long long a){
    return a<0?-a:a;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
            int n;
            scanf("%d",&n);
            long long s[n+2],an[n+2][2][2];;
            memset(s,0,sizeof s);
            memset(an,0,sizeof an);
            for(int i=1;i<=n;i++){
                scanf("%lld",&s[i]);
            }
            //值得注意的是前两个元素比较特殊,不能利用方程递推出来,因此要手动写出其状态
            an[1][0][0]=0;
            an[2][0][0]=abbs(s[1]-s[2]);
            an[2][1][0]=0;
            an[2][1][1]=0;
            for(int i=3;i<=n;i++){
                    an[i][0][0]=an[i-1][0][0]+abbs(s[i]-s[i-1]);
                    an[i][1][0]=min(an[i-1][1][0]+abbs(s[i]-s[i-1]),an[i-1][1][1]+abbs(s[i]-s[i-2]));
                    an[i][1][1]=an[i-1][0][0];
            }
            printf("%lld\n",min(min(an[n][0][0],an[n][1][0]),an[n][1][1]));
        }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值