codeforces 1131F Moving Point
题目:
There are n points on a coordinate axis OX. The i-th point is located at the integer point xi and has a speed vi. It is guaranteed that no two points occupy the same coordinate. All n points move with the constant speed, the coordinate of the i-th point at the moment t (t can be non-integer) is calculated as xi+t⋅vi.
Consider two points i and j. Let d(i,j) be the minimum possible distance between these two points over any possible moments of time (even non-integer). It means that if two points i and j coincide at some moment, the value d(i,j) will be 0.
Your task is to calculate the value ∑1≤i<j≤n d(i,j) (the sum of minimum distances over all pairs of points).
Input
The first line of the input contains one integer n (2≤n≤2⋅105) — the number of points.
The second line of the input contains n integers x1,x2,…,xn (1≤xi≤108), where xi is the initial coordinate of the i-th point. It is guaranteed that all xi are distinct.
The third line of the input contains n integers v1,v2,…,vn (−108≤vi≤108), where vi is the speed of the i-th point.
Output
Print one integer — the value ∑1≤i<j≤n d(i,j) (the sum of minimum distances over all pairs of points).
大意
求所有点两两之间最小距离的总和。若他们能相交则记0
解题思路
1.对两点x1,x2不妨设x1<x2,当v1<=v2时,对答案的贡献是x2-x1,否则为0
2.将所所有点进行排序,对每个点i求所有xj<xi&&vj<=vi的点的距离,
对答案的贡献是cnt*xi-Σxj,可以用线段树或树状数组来存储Σxj和vj<=vi的次数
3.-1e8<=speed<=1e8,数字过大,需要进行离散化
代码实现
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=2e5+5;
typedef long long ll;
struct P{
int x,speed;
}a[N];
ll cnt[N],dis[N];
bool cmp(P&p1 , P&p2 ){
return p1.x<p2.x;
}
vector<int > sp;
unordered_map<int,int > m;
int n;
int lowbit(int x){
return x&(-x);
}
void update(int pos,int x){
while(pos<=n){
cnt[pos]+=1;
dis[pos]+=x;
pos+=lowbit(pos);
}
}
ll get_res(int pos,int x){
ll t=0,tot=0,res=0;
while(pos>0){
t+=cnt[pos];
tot+=dis[pos];
pos-=lowbit(pos);
}
res=t*x-tot;
return res;
}
ll ans=0;
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i].x;
for(int i=1;i<=n;i++){
cin>>a[i].speed;
sp.pb(a[i].speed);//记录每个点和每个点的速度
}
sort(a+1,a+1+n,cmp);//对点进行排序
sort(sp.begin(),sp.end());//对速度大小进行排序, 便于离散化
sp.erase(unique(sp.begin(),sp.end()),sp.end());//删除重复的速度
for(int i=0;i<n;i++)m[sp[i]]=i+1;
for(int i=1;i<=n;i++){
ans+=get_res(m[a[i].speed],a[i].x);//将xj<xi&&vj<=vi的点都加上
update(m[a[i].speed],a[i].x);// 更新
}
cout<<ans;
return 0;
}