题目链接: https://ac.nowcoder.com/acm/contest/5403/A
本来只是给校赛作为一个简单题,没想到杀疯了orz(通过率只有不到5%
不知道为啥暴力复杂度达到了1e10还有这么多人敢冲
用两个数组分别储存员工数目的前缀和以及员工坐标的前缀和,记为sum1和sum2。
对于一套方案中的两个工位a,b(假设a<b),令mid=(a+b)/2,易知在[1,mid]范围内的员工到a点更近,在[mid+1, 105]范围内的员工到b点更近。
对于要到a的员工,分为不在a的右侧和在a的右侧两类。
//计算不在a右侧要到a的员工的答案(即在[1,a]内的员工
ans+=sum1[a]*a-sum2[a];
//计算在a右侧要到a的员工的答案(即在[a+1,mid]内的员工
ans+=(sum2[mid]-sum2[a])-(sum1[mid]-sum1[a])*a
要到b的员工同理,加起来就可以得到答案了。
std:
#include <bits/stdc++.h>
#define N 100000
using namespace std;
typedef long long ll;
ll n, q, ans;
ll sum1[N+10], sum2[N+10];
int main()
{
cin>>n>>q;
for (int i=1, x; i<=n; i++)
{
cin>>x;
sum1[x]++, sum2[x]+=x;
}
for (int i=1; i<=N; i++)
sum1[i]+=sum1[i-1], sum2[i]+=sum2[i-1];
for (int i=1, a, b, mid; i<=q; i++)
{
cin>>a>>b;
if (a>b) swap(a, b);
ans=0, mid=(a+b)/2;
ans+=sum1[a]*a-sum2[a];//[1,a]
ans+=sum2[mid]-sum2[a]-(sum1[mid]-sum1[a])*a;//[a+1,mid]
ans+=(sum1[b]-sum1[mid])*b-(sum2[b]-sum2[mid]);//[mid+1, b]
ans+=sum2[N]-sum2[b]-(sum1[N]-sum1[b])*b;//[b+1, N]
cout<<ans<<"\n";
}
return 0;
}