F. Moving Points

Posted lijiahui-123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了F. Moving Points相关的知识,希望对你有一定的参考价值。

There are nn points on a coordinate axis OXOX . The ii -th point is located at the integer point xixi and has a speed vivi . It is guaranteed that no two points occupy the same coordinate. All nn points move with the constant speed, the coordinate of the ii -th point at the moment tt (tt can be non-integer) is calculated as xi+tvixi+t⋅vi .

Consider two points ii and jj . Let d(i,j)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 ii and jj coincide at some moment, the value d(i,j)d(i,j) will be 00 .

Your task is to calculate the value 1i<jn∑1≤i<j≤n d(i,j)d(i,j) (the sum of minimum distances over all pairs of points).

Input

The first line of the input contains one integer nn (2n21052≤n≤2⋅105 ) — the number of points.

The second line of the input contains nn integers x1,x2,,xnx1,x2,…,xn (1xi1081≤xi≤108 ), where xixi is the initial coordinate of the ii -th point. It is guaranteed that all xixi are distinct.

The third line of the input contains nn integers v1,v2,,vnv1,v2,…,vn (108vi108−108≤vi≤108 ), where vivi is the speed of the ii -th point.

Output

Print one integer — the value 1i<jn∑1≤i<j≤n d(i,j)d(i,j) (the sum of minimum distances over all pairs of points).

Examples
Input
Copy
3
1 3 2
-100 2 3
Output
Copy
3
Input
Copy
5
2 1 4 3 5
2 2 2 3 4
Output
Copy
19
Input
Copy
2
2 1
-3 0
Output
Copy
0

题解:

Tutorial

1311F - Moving Points

Let‘s understand when two points ii and jj coincide. Let xi<xjxi<xj . Then they are coincide when vi>vjvi>vj . Otherwise, these two points will never coincide and the distance between them will only increase.

So, we need to consider only the initial positions of points. Let‘s sort all points by xixi and consider them one by one from left to right. Let the ii -th point be the rightmost in the pair of points that we want to add to the answer.

We need to find the number of points jj such that xj<xixj<xi and vjvivj≤vi and the sum of xjxj for such points as well. We can do this using two BITs (Fenwick trees) if we compress coordinates (all values vv ) and do some kind of "scanline" by values xx . Let the number of such points be cntcnt and the sum of coordinates of such points be sumsum . Then we can increase the answer by xicntsumxi⋅cnt−sum and add our current point to the Fenwick trees (add 11 to the position vivi in the first tree and xixi to the position vivi in the second tree). When we want to find the number of required points and the sum of its coordinates, we just need to find the sum on the prefix two times in Fenwick trees. Note that you can use any "online" logarithmic data structure you like in this solution (such as treap and segment tree).

There is also another solution that uses pbds. Let‘s do the same thing, but there is one problem. Such data structure does not have "sum on prefix" function, so we have to replace it somehow. To do this, let‘s calculate only xicntxi⋅cnt part when we go from left to right. Then let‘s clear our structure, go among all points again but from right to left and calculate the same thing, but with the opposite sign (find the number of points jj such that xj>xixj>xi and vjvivj≥vi ). When we go from right to left, we need to decrease the answer by xicntxi⋅cnt . It is some kind of "contribution to the sum" technique.

Time complexity: O(nlogn)O(nlog?n) .

 

Solution (Fenwick tree)

#include <bits/stdc++.h>

using namespace std;

long long get(vector<long long> &f, int pos) {
	long long res = 0;
	for (; pos >= 0; pos = (pos & (pos + 1)) - 1)
		res += f[pos];
	return res;
}

void upd(vector<long long> &f, int pos, int val) {
	for (; pos < int(f.size()); pos |= pos + 1) {
		f[pos] += val;
	}
}

int main() {
#ifdef _DEBUG
	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif
	
	int n;
	cin >> n;
	vector<pair<int, int>> p(n);
	for (auto &pnt : p) cin >> pnt.first;
	for (auto &pnt : p) cin >> pnt.second;
	sort(p.begin(), p.end());
	
	vector<int> vs;
	for (auto &pnt : p) vs.push_back(pnt.second);
	sort(vs.begin(), vs.end());
	vs.resize(unique(vs.begin(), vs.end()) - vs.begin());
	
	long long ans = 0;
	vector<long long> cnt(vs.size()), xs(vs.size());
	for (auto &pnt : p) {
		int pos = lower_bound(vs.begin(), vs.end(), pnt.second) - vs.begin();
		ans += get(cnt, pos) * 1ll * pnt.first - get(xs, pos);
		upd(cnt, pos, 1);
		upd(xs, pos, pnt.first);
	}
	
	cout << ans << endl;
	
	return 0;
}


Solution (pbds)
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef
tree<
	pair<int, int>,
	null_type,
	less<pair<int, int>>,
	rb_tree_tag,
	tree_order_statistics_node_update>
ordered_set;

int main() {
#ifdef _DEBUG
	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif
	
	int n;
	cin >> n;
	vector<pair<int, int>> p(n);
	for (auto &pnt : p) cin >> pnt.first;
	for (auto &pnt : p) cin >> pnt.second;
	sort(p.begin(), p.end());
	
	ordered_set s;
	long long ans = 0;
	for (int i = 0; i < n; ++i) {
		int cnt = s.order_of_key(make_pair(p[i].second + 1, -1));
		ans += cnt * 1ll * p[i].first;
		s.insert(make_pair(p[i].second, i));
	}
	s.clear();
	for (int i = n - 1; i >= 0; --i) {
		int cnt = int(s.size()) - s.order_of_key(make_pair(p[i].second - 1, n));
		ans -= cnt * 1ll * p[i].first;
		s.insert(make_pair(p[i].second, i));
	}
	
	cout << ans << endl;
	
	return 0;
}


//转载于http://codeforces.com/blog/entry/74224

以上是关于F. Moving Points的主要内容,如果未能解决你的问题,请参考以下文章

codeforces 1311F Moving Points 两种解法

[CodeForces] Moving Points

hdu 4717(三分) The Moving Points

The 2019 Asia Yinchuan First Round Online Programming F. Moving On

HDU-4717 The Moving Points(凸函数求极值)

题解CF1311F Moving Points