题目链接:https://ac.nowcoder.com/acm/contest/5403/A
题目大意:
给出n个人的位置(同一位置可能会有多人),q套方案,对于每个方案(两个位置),求出所有人到达两位置中的一个的最小距离和。
思路:
数据范围较大,暴力会超时,这时就需要提前进行处理,给出的两个位置假设为a,b(a < b),a位置之前的人到a的距离最小,b位置之后的人到b的距离最小,a~b范围内的,可以以 (a+b)/2 划分同前面方法分析。举例情况一:假设a位置前有m个人,位置和为sum,则这些人到a位置的距离和为 (a * m - sum)。所以需要预处理每个人所有工位的前缀人数和以及位置前缀和。
解题代码:
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cmath> 5 #include <string> 6 #include <cstring> 7 using namespace std; 8 const long long N = 1e10 + 7; 9 const int maxn = 1e5 + 5; 10 const long long INF = 8e18; 11 typedef long long ll; 12 #define for0(i,n) for(int i = 0;i < n;i++) 13 #define for1(i,n) for(int i = 1;i <= n;i++) 14 ll x[maxn],w[maxn]; 15 int main() 16 { 17 18 int n,q,m; 19 cin >> n >> q; 20 for1(i,n){ 21 cin >> m; 22 x[m]++; 23 w[m] += m; 24 } 25 for1(i,100000){ 26 x[i] += x[i-1]; //前缀个数和 27 w[i] += w[i-1]; //前缀和 28 } 29 while(q--){ 30 int a,b; 31 cin >> a >> b; 32 if(a > b) 33 swap(a,b); 34 ll sum = 0; 35 sum += a * x[a] - w[a]; 36 sum += (w[100000] - w[b]) - b * (x[100000] - x[b]); 37 sum += (w[(b+a)/2] - w[a]) - a * (x[(b+a)/2] - x[a]); 38 sum += b * (x[b] - x[(b+a)/2]) - (w[b] - w[(b+a)/2]); 39 cout << sum << endl; 40 } 41 42 return 0; 43 }