1. 程式人生 > >VK Cup 2018 Round 2: D. Contact ATC(思維+樹狀陣列)

VK Cup 2018 Round 2: D. Contact ATC(思維+樹狀陣列)

time limit per test 1 secondmemory limit per test 256 megabytesinput standard inputoutput standard output

Arkady the air traffic controller is now working with n planes in the air. All planes move along a straight coordinate axis with Arkady's station being at point 0 on it. The i-th plane, small enough to be represented by a point, currently has a coordinate of x

i and is moving with speed vi. It's guaranteed that xi·vi < 0, i.e., all planes are moving towards the station.

Occasionally, the planes are affected by winds. With a wind of speed vwind (not necessarily positive or integral), the speed of the i-th plane becomes vi + vwind.

According to weather report, the current wind has a steady speed falling inside the range [ - w

, w] (inclusive), but the exact value cannot be measured accurately since this value is rather small — smaller than the absolute value of speed of any plane.

Each plane should contact Arkady at the exact moment it passes above his station. And you are to help Arkady count the number of pairs of planes (i

, j) (i < j) there are such that there is a possible value of wind speed, under which planes i and j contact Arkady at the same moment. This value needn't be the same across different pairs.

The wind speed is the same for all planes. You may assume that the wind has a steady speed and lasts arbitrarily long.

Input

The first line contains two integers n and w (1 ≤ n ≤ 100 0000 ≤ w < 105) — the number of planes and the maximum wind speed.

The i-th of the next n lines contains two integers xi and vi (1 ≤ |xi| ≤ 105w + 1 ≤ |vi| ≤ 105xi·vi < 0) — the initial position and speed of the i-th plane.

Planes are pairwise distinct, that is, no pair of (i, j) (i < j) exists such that both xi = xj and vi = vj.

Output

Output a single integer — the number of unordered pairs of planes that can contact Arkady at the same moment.

Examplesinput
5 1
-3 2
-3 3
-1 2
1 -3
3 -5
output
3
input
6 1
-3 2
-2 2
-1 2
1 -2
2 -2
3 -2
output
9

這題難在卡精度吧。。其實只用排兩次序然後一個很簡單的樹狀陣列就搞定了

題意:在數軸上有n架飛機,它們的的位置分別是x[i],它們各以v[i]的速度,朝著原點移動(x[i]*v[i]<0),可是按道理這個時候是有風的,風的範圍是[-w, w],你不知道風具體多大,只知道無論風多大每架飛機都一定還可以到達原點(也就是不會被吹不動或者 變成反方向),問你有多少架飛機可能在某個情況下同時到達原點

也就是問有多少對點滿足方程的解p∈[-w, w]

對這個方程求導你就會發現關於p的函式是單調的,這就意味著當且僅當p = -w或者p = w時方程f(p)取得極值

這也就意味著:對於飛機A和B,如果在風速為-w時,A先到達原點,而在風速為w時B先到達點,那麼A和B就有可能同時到達原點,這道題就是統計有多少對飛機滿足這個要求

具體怎麼統計呢?

先按風速為-w時每架飛機到達原點時間排序,再按風速為w時每架飛機到達遠點排序,如果A和B滿足在這兩個序列中偏序不同,就說明他們可以同時到達原點,統計很好辦,按照第一個排序序列一個一個的將飛機加入樹狀陣列,然後在第二個排序序列中查詢它前面還有多少架飛機沒有加入樹狀陣列中就OK了,複雜度O(nlogn)

為什麼會卡常數?

因為有可能剛好風速為-w和w時兩架飛機在原點相遇,即函式f(p)在極值點時值為0,這個時候它們在某個序列中應該沒有順序可言,而這個時候按順序統計就有可能出錯

解決方法①:很容易想到其實只要將w加上一個很小的值就可以搞定了,我就是這個方法,但是這個值是多少就很難說了,太大了可能本來無法相遇算成相遇,太小了精度有損失,我試了當這個值為0.00001的時候剛好AC

解決方法②:除法計算改成乘法計算,然後排序之前將飛機離散化,這樣應該答案一定是對的,但很麻煩就是了

#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
#define LL long long
typedef struct Res
{
	int id;
	double x, v;
	bool operator < (const Res &b) const
	{
		if(fabs(x*b.v)<fabs(v*b.x))
			return 1;
		return 0;
	}
}Point;
Point s[100005];
int n, a[100005], b[100005], tre[100005];
int Query(int k)
{
	int ans = 0;
	while(k)
	{
		ans += tre[k];
		k -= k &-k;
	}
	return ans;
}
void Update(int k, int val)
{
	while(k<=n)
	{
		tre[k] += val;
		k += k&-k;
	}
}
int main(void)
{
	int i;
	LL ans;
	double w;
	scanf("%d%lf", &n, &w);
	w += 1e-6;
	for(i=1;i<=n;i++)
	{
		scanf("%lf%lf", &s[i].x, &s[i].v);
		s[i].id = i, s[i].v -= w;
	}
	sort(s+1, s+n+1);
	for(i=1;i<=n;i++)
		a[i] = s[i].id;
	for(i=1;i<=n;i++)
		s[i].v += 2*w;
	sort(s+1, s+n+1);
	for(i=1;i<=n;i++)
		b[s[i].id] = i;
	ans = 0;
	for(i=1;i<=n;i++)
	{
		ans += i-1-Query(b[a[i]]);
		Update(b[a[i]], 1);
	}
	printf("%lld\n", ans);
	return 0;
}