题目:张经理的员工

题目链接: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 }