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

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