Codeofrces 957E 数学二维偏序

题目链接:http://codeforces.com/contest/957/problem/E

E. Contact ATC
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
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 xi 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 000, 0 ≤ 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| ≤ 105, w + 1 ≤ |vi| ≤ 105, xi·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.

Examples
Input
Copy
5 1
-3 2
-3 3
-1 2
1 -3
3 -5
Output
3
Input
Copy
6 1
-3 2
-2 2
-1 2
1 -2
2 -2
3 -2
Output
9
Note

In the first example, the following 3 pairs of planes satisfy the requirements:

  • (2, 5) passes the station at time 3 / 4 with vwind = 1;
  • (3, 4) passes the station at time 2 / 5 with vwind = 1 / 2;
  • (3, 5) passes the station at time 4 / 7 with vwind =  - 1 / 4.

In the second example, each of the 3 planes with negative coordinates can form a valid pair with each of the other 3, totaling 9 pairs.

题意:给出一个坐标轴,给出一个风速范围【-W,+W】。给出每架飞机的当前位置和速度,并且飞机分布在原点两侧,问有多少架飞机可以在某个相同风速下同时到达原点。

题解:首先要糊一个结论:对于一对飞机,如果风速分别为w和-w时,两个飞机分别先到达原点,那么存在风速使得两架飞机同时到达原点。

       那么对于所有的飞机,求出风速为w和-w时到原点的时间tx, ty, 若两个飞机i,j可以同时到达原点只要(txi-tyi)*(tyi-tyj) <= 0即可,所以我们按照txi从小到达排序,注意txi==txj时候,按照tyi > tyj来排,不然答案会减少,然后就是个二维偏序问题了,用树状数组解决。注意直接除法存在精度问题,我们需要手写分数。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef long double ld;

#define x0 x0___
#define y0 y0___
#define pb push_back
#define SZ(X) ((int)X.size())
#define mp make_pair
#define fi first
#define se second
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pli pair<ll,int>
#define pil pair<int,ll>
#define ALL(X) X.begin(),X.end()
#define RALL(X) X.rbegin(),X.rend()
#define rep(i,j,k) for(int i = j;i <= k;i ++)
#define per(i,j,k) for(int i = j;i >= k;i --)
#define mem(a,p) memset(a,p,sizeof(a))


const ll MOD = 1E9 + 7;
ll qmod(ll a,ll b,ll c) {ll res=1;a%=c; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%c;a=a*a%c;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}

template<typename T, typename S>
void upmax(T& a,S b){if(a<b) a=b;}
template<typename T, typename S>
void upmin(T& a,S b){if(a>b) a=b;}
template<typename T>
void W(T b){cout << b << endl;}
void gettle() {while(1);}
void getre() {int t=0;t/=t;}


/
/
/
/


const int N = 1E5 + 7;


struct frac
{
    int fz, fm;
    frac(){}
    frac(int _1,int _2):fz(_1),fm(_2){}
    bool operator == (const frac &p) const {
        return (ll)fz*p.fm == (ll)p.fz*fm;
    }
    bool operator < (const frac &p) const {
        return (ll)fz*p.fm < (ll)p.fz*fm;
    }
}b[N];

struct node
{
    frac x, y;
    int pos;
    bool operator < (const node &p) const {
        return x == p.x ? pos > p.pos : x < p.x; //按照飞机以v+w排序,注意相等时候,要按照v-w后到在前的顺序排序,否则统计他之前比他大的数的时候会少算
    }
}a[N];
int n, w, m;
int bit[N];
void add(int p, int d)
{
    for(;p<=m;p+=p&-p) bit[p] += d;
}
int ask(int p)
{
    int s = 0;
    for(;p;p-=p&-p) s += bit[p];
    return s;
}

int main()
{
    scanf("%d %d", &n, &w);
    rep (i,1,n) {
        int x, v;
        scanf("%d %d", &x, &v);
        a[i].x = frac(abs(x), abs(v+w));
        a[i].y = frac(abs(x), abs(v-w));
        b[i] = a[i].y;
    }
    sort(b+1, b+1+n);
    m = unique(b+1,b+1+n) - (b+1);

    rep(i,1,n) a[i].pos = lower_bound(b+1, b+1+m, a[i].y) - b;
    sort(a+1, a+1+n);
    ll res = 0;
    rep (i,1,n) {
        res += (i - 1 - ask(a[i].pos-1));//这一步关键,巧妙的统计当前>=a[i].pos的数有多少个.
        add(a[i].pos, 1);
    }
    printf("%lld\n",res);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值