Codeforces Round #688 (Div. 2) B. Suffix Operations(差分)

Gildong has an interesting machine that has an array 𝑎a with 𝑛n integers. The machine supports two kinds of operations:

  1. Increase all elements of a suffix of the array by 1.
  2. Decrease all elements of a suffix of the array by 1.

A suffix is a subsegment (contiguous elements) of the array that contains 𝑎𝑛an. In other words, for all 𝑖 where 𝑎𝑖ai is included in the subsegment, all 𝑎𝑗's where 𝑖<𝑗≤𝑛 must also be included in the subsegment.

Gildong wants to make all elements of 𝑎a 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 𝑡(1≤𝑡≤1000).

Each test case contains two lines. The first line of each test case consists of an integer 𝑛(2≤𝑛≤2⋅105) — the number of elements of the array 𝑎.

The second line of each test case contains 𝑛n integers. The 𝑖-th integer is 𝑎𝑖(−5⋅108≤𝑎𝑖≤5⋅108).

It is guaranteed that the sum of 𝑛n in all test cases does not exceed 2⋅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

Copy

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

Copy

0
1
3
4
6
5
2847372102

大意是给定一个数组,每次可以对其某个后缀全部+1 or -1,问操作最少多少次能使整个数组全部变为同一个数。为了加快速度,可以在操作前把某一个数变成任意一个数。

好久没打cf了,40min才过了这个题QAQ

看到区间加/减很容易想到差分,因为每次操作的都是后缀,因此不用管右端点,只需要看左端点。考虑差分的定义,对l~r整体+1就是diff[l] + 1, diff[r + 1] - 1,而这个题的r就是n + 1不用管,总的操作次数就是:

Σi=2nabs(diff[i])

但是因为一开始可以变任意一个数,同时想到如果修改一个数a[i],那么对差分数组影响的仅仅是diff[i]和diff[i + 1],那么我们考虑枚举一开始变的数的位置,更改其对答案的贡献即可。

比如对于位置x,如果要改变它的话应该把它变成什么才能使结果最优呢?答案是把它变为任何介于a[x - 1]和a[x + 1]之间的数即可。因为对于这个题要把差分数组求绝对值,按照上述情况操作的话对于最终答案的贡献都是一样的,且最优(可以手动模拟一下)。然后要做的就是枚举每个位置了,先减去原来的贡献再加上修改后的贡献。特别注意的是第一个数应该修改为a[2],最后一个数应该修改为a[i - 1]。

#include <iostream>
using namespace std;
long long n, a[200005];
long long diff[200005];
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        cin >> n;
        a[0] = 0;
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        long long cnt = 0, mmax = 0;
        for (int i = 1; i <= n; i++)
        {
            diff[i] = a[i] - a[i - 1];
            if(i != 1)
            {
                cnt += abs(diff[i]);                
            }
        }
        long long ans = 1e17;
        for(int i = 2; i <= n; i++)
        {
            long long tmp = cnt;
            tmp -= abs(diff[i]);
            if(i != n) //特殊处理n
            {
                tmp -= abs(diff[i + 1]);
                tmp += abs(a[i + 1] - a[i - 1]);//新的贡献
            }
            ans = min(ans, tmp);
        }
        long long tmp = cnt;//特殊处理修改第一个数的情况
        tmp -= abs(diff[2]);
        ans = min(ans, tmp);
        cout << ans << endl;
    }
    return 0;
}
posted @   脂环  阅读(162)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示
主题色彩