codeforces 1131F Moving Point(树状数组+离散化)

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;
}

猜你喜欢

转载自blog.csdn.net/qq_20252251/article/details/104858450