Codeforces Round #624 (Div. 3) F. Moving Points /详解

F. Moving Points
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
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).

Examples
inputCopy
3
1 3 2
-100 2 3
outputCopy
3
inputCopy
5
2 1 4 3 5
2 2 2 3 4
outputCopy
19
inputCopy
2
2 1
-3 0
outputCopy
0

题意:
给出一些在座标轴上的质点,带着位置和速度的属性,求 两两质点最小dis(i,j)之和。

思路:

  1. 本来是不想写的,因为这个是赛后才补上的套路题,但翻了翻网上的题解几乎都是直接贴代码,索性就开一篇以后自己可以回顾。
  2. 问题求的是最小距离之和,可以发现这个距离只有两种情况:
  3. 一种是 xi<xj && vi<vj 这样 i 永远追不上j 所以 min dis= xj - xi
  4. 其他情况 便是 i 能够与 j 重合 ,这种情况 min dis = 0
  5. 每个点对答案的贡献= 比自己小的点数*xi - 比自己小的点的座标和
  6. 可以发现除了xi 其他两个变量都与和有关,这个时候就要联想到树状数组or线段树。
  7. 所以可以把点集排个序,再把速度离散化,依次遍历即可。

代码:

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#define ll long long
//#define ll unsigned long long
#define inf 0x3f3f3f3f
#define mod 1000000007
#define eps 1e-6
#define pi acos(-1)
#define myit set<ll>::iterator
#define mysets multiset<ll>
#define myits multiset<ll>::iterator
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
using namespace std;
inline ll read(){
   ll s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
using namespace std;
ll qpf(ll a, ll b, ll p)
{ll ret = 0;while(b){if(b & 1) ret = (ret + a) % p;
a = (a + a) % p;b >>= 1;}return ret % p ;}
ll qp(ll a, ll n, ll p)
{ll ret = 1;while(n){if(n & 1) ret = qpf(ret, a, p);a = qpf(a, a, p);
n >>= 1;}return ret % p ;}

const int manx=2e5+5;
struct node{
    ll x,v;
}a[manx];
bool cmp(node a,node b){return a.x<b.x;}
ll maps[manx],s[manx][2];
ll ans=0,n;
void add(ll x, ll val){
    while(x<=n){
        s[x][0]++;
        s[x][1]+=val;
        x+=lowbit(x);
    }
}
ll gets(ll x,ll k){
    ll res=0;
    while(x){
        res+=s[x][k];
        x-=lowbit(x);
    }
    return res;
}
int main()
{
    n=read();
 	for(int i=1;i<=n;i++) a[i].x=read();
 	for(int i=1;i<=n;i++) a[i].v=maps[i]=read();
 	sort(a+1,a+1+n,cmp);
 	sort(maps+1,maps+1+n);
 	ll m=unique(maps+1,maps+1+n)-maps-1;
 	ll ans=0;
 	for(int i=1;i<=n;i++){
        ll x=lower_bound(maps+1,maps+1+m,a[i].v)-maps;
        ans+=a[i].x*gets(x,0)-gets(x,1);
        add(x,a[i].x);
 	}
 	cout<<ans<<endl;
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章