Whu 1603——Minimum Sum——————【单个元素贡献、滑窗】
Problem 1603 - Minimum Sum
Time Limit: 2000MS Memory Limit: 65536KB
Total Submit: 623 Accepted: 178 Special Judge: No
Total Submit: 623 Accepted: 178 Special Judge: No
Description
There are n numbers A[1] , A[2] .... A[n], you can select m numbers of it A[B[1]] , A[B[2]] ... A[B[m]] ( 1 <= B[1] < B[2] .... B[m] <= n ) such that Sum as small as possible.
Sum is sum of abs( A[B[i]]-A[B[j]] ) when 1 <= i < j <= m.
Input
There are multiple test cases.
First line of each case contains two integers n and m.( 1 <= m <= n <= 100000 )
Next line contains n integers A[1] , A[2] .... A[n].( 0 <= A[i] <= 100000 )
It's guaranteed that the sum of n is not larger than 1000000.
First line of each case contains two integers n and m.( 1 <= m <= n <= 100000 )
Next line contains n integers A[1] , A[2] .... A[n].( 0 <= A[i] <= 100000 )
It's guaranteed that the sum of n is not larger than 1000000.
Output
For each test case, output minimum Sum in a line.
Sample Input
4 2
5 1 7 10
5 3
1 8 6 3 10
5 1 7 10
5 3
1 8 6 3 10
Sample Output
2
8
8
题目大意:让你从n个数中挑出m个,求这m个数中任意两个元素差的绝对值,然后求和。问你最小的绝对值和为多少。
解题思路:首先可以确定的是,如果挑出的m个数越平稳,那么绝对值和最小。(当时没考虑到只要排序后,就是最平稳的了)所以问题转化成,如何求排序后的n个元素的序列中m个相连元素差的绝对值和最小。滑动窗口(计算机网络中的名词),当加入a[i]时,a[i-m]就要退出来,始终保证只有m个元素。那么只需要考虑加入和退出元素产生的贡献。
#include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<iostream> using namespace std; const int maxn = 1e5+200; typedef long long LL; int a[maxn], sum[maxn]; int main(){ int n, m; while(scanf("%d%d",&n,&m)!=EOF){ for(int i = 1; i <= n; i++){ scanf("%d",&a[i]); } sort(a+1,a+1+n); for(int i = 1; i <= n; i++){ sum[i] = sum[i-1]+a[i]; } int ans = 0, tmp; for(int i = 2; i <= m; i++){ ans += a[i]*(i-1) - (sum[i-1] - sum[0]); } tmp = ans; if(n == m){ printf("%d\n",ans); continue; } for(int i = m+1; i <= n; i++){ tmp = tmp + a[i]*(m-1) - (sum[i-1] - sum[i-m]) - ((sum[i-1]-sum[i-m]) - a[i-m]*(m-1)); ans = min(ans,tmp); } printf("%d\n",ans); } return 0; }
学学学 练练练 刷刷刷