[KOI 2021 Round 2] 累计距离
Ghosty_Neutrino · · 题解
题意
数轴上有
分析
根据绝对值的性质,可以得到两种情况:
- 当
x_i \leq q 时,|x_i - q| = q - x_i 。 - 当
x_i > q 时,|x_i - q| = x_i - q 。
累计距离可拆分为两部分计算:
预处理这两部分的前缀和,就能快速计算累计距离,所以接下来我们就来预处理一下这两个部分。
首先将村庄按位置
定义数组
接下来用二分查找分割点,使用二分查找找到第一个满足
于是我们可以累计距离啦,分左右分别计算,左边有
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,q,k;
ll o,l,r;
struct D{
ll x,a;
bool operator<(const D&w)const{return x<w.x;}
};
int main() {
ios::sync_with_stdio(false);//快读快写启动,我怕炸TLE
cin.tie(nullptr);
cin>>n>>q;
vector<D> v(n);
for(int i=0;i<n;i++) cin>>v[i].a>>v[i].x;
sort(v.begin(),v.end());
vector<ll> suma(n+1,0);//前i个村庄的a总和
vector<ll> sumax(n+1,0);//前i个村庄的a*x总和
for(int i=0;i<n;i++){
suma[i+1]=suma[i]+v[i].a;
sumax[i+1]=sumax[i]+v[i].a*v[i].x;
}
for (int i=0;i<q;i++){
cin>>o;
k=lower_bound(v.begin(),v.end(),D{o,0})-v.begin();//二分查找第一个x>=q的村庄下标
l=o*suma[k]-sumax[k];//左边的距离
r=(sumax[n]-sumax[k])-o*(suma[n]-suma[k]);//右边的距离
cout<<l+r<<endl;
}
return 0;
}