题目描述
洛洛在外出旅游的时候发现社会上文明的现象越来越多,人们在买票的时候都会自发地排队等候。
遗憾的是排队的人身高参差不齐,有时候前后两人之间的身高相差太大,缺乏一些美感。
如果把前后两人的身高差(差值为正数)表示为两者前后相邻时产生的违和度,一段连续的人群因为前后两人身高不同而产生的违和度之和就可以被称为违和值。洛洛希望知道在队伍哪一段,且该段队伍由连续的m个人组成,其违和值最小。
输入
第一行输入两个正整数 n,m,n表示队伍的总人数,m表示某一段的人数。
第二行输入n个整数,表示队伍中n个人的身高(单位:厘米)。
输出
输出包含一个整数,即最小的违和值。
样例输入 Copy
样例输入1 4 3 1 2 4 7 样例输入2 4 3 10 7 5 4
样例输出 Copy
样例输出1 3 样例输出2 3
提示
样例2说明:m=3,要选取3个连续的人有两种选法:
10 7 5: 违和度之和=3+2=5
7 5 4: 违和度之和=2+1=3
所以答案是3。
对于50%的数据保证2 ≤ n ≤ 10;
对于80%的数据保证2 ≤ n ≤ 1000;
对于100%的数据保证2 ≤ n ≤ 100000,1 ≤ m < n,每个人的身高不超过300厘米。
解题思路:此题就是用前缀和来求区间元素的和, 如果暴力肯定会超时。
Code:
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <iomanip>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef int Status;
const int N = 1e5 + 30;
LL n, x, y, z, m, tt = -1, hh, k, minn = 999999999, ans;
int q[N], a[N], b[N], s[N];
signed main()
{
cin >> n >> m;
y = m - 1;
for(int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
for(int i = 1; i <= n - 1; i ++ ) b[i] = fabs(a[i + 1] - a[i]);
for(int i = 1; i <= n - 1; i ++ ) s[i] = s[i - 1] + b[i]; //前缀和
for(int i = 1; i <= n - y; i ++ )
{
ans = fabs(s[i + y - 1] - s[i - 1]);
minn = min(ans, minn);
}
cout << minn << endl;
}