第五届华中区程序设计邀请赛暨武汉大学第十四届校赛 网络预选赛 A Minimum Sum 树状数组
Problem 1603 - Minimum Sum
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个数来,使得 sigma abs( A[B[i]]-A[B[j]] ) when 1 <= i < j <= m.最小
题解:
排序过后,就是选择连续的m个数了
由于数的范围小,我们在统计连续和的时候 利用BIT优化
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <queue> #include <vector> using namespace std; const int N = 1e5+10, M = 50, mod = 1e9+9, inf = 1e9+9; typedef long long ll; ll sum; int n,m,a[N]; int C[N],A[N]; int lowbit(int x) { return x&(-x); } void add(int x, int add) { for (; x < N; x += lowbit(x)) { C[x] += add; } } int sums(int x) { int s = 0; for (; x > 0; x -= lowbit(x)) { s+=C[x]; } return s; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { memset(C,0,sizeof(C)); for(int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+n+1); sum = 0; for(int i=1;i<=m;i++) { sum+=(a[i]*(i-1)-sums(i)); add(i,a[i]); } // cout<<sum<<endl; ll ans = sum; for(int i=m+1;i<=n;i++) { sum -= (sums(i)-sums(i-m)-a[i-m]*(m-1)); // cout<<(sums(i)-sums(i-m+1)-a[i-m]*(m-1))<<endl; // cout<<sum<<endl; sum += (a[i]*(m-1)-sums(i)+sums(i-m)); add(i,a[i]); ans = min(ans,sum); } printf("%lld\n",ans); } return 0; }