Description

NBA 每年都有球员选秀环节. 通常用速度和身高两项数据来衡量一个篮球运动员的基本素质. 假如一支球队里速度最慢的球员速度为 \(minV\), 身高最矮的球员高度为 \(minH\), 那么这支 球队的所有队员都应该满足:\(a \times (height - minH) + b \times (speed - minV) \leq c\), 其中 \(a, b, c\) 为给定的经验值. 这个式子很容易理解, 如果一个球队的球员速度和身高 差距太大, 会造成配合的不协调. 请问作为球队管理层的你, 在 \(n\) 名选秀球员中, 最多 能有多少名符合条件的候选球员.

Input

第一行四个数 \(n, a, b, c\)

下接 \(n\) 行每行两个数描述一个球员的 \(height\)\(speed\)

Output

最多候选球员数目.

Sample Input

4 1 2 10
5 1
3 2
2 3
2 1

Sample Output

4

Data Range

对于所有数据, 满足:\(n \leq 5000, height, speed \leq 10000, a, b, c \leq 2^{31}-1\)

Explanation

在一定的范围内如果将他们的权值排序会发现其实是具有单调性的. 所以说, 虽然转移的时间复杂度是每次 \(O(n^2)\) 的, 但是我们可以保证均摊是 \(O(n^2)\) 的.

这样一来, 只需要暴力枚举速度下限和身高下限就可以了, 余下的在已经排序的数组上瞎搞 一发就可以解决问题了 (减号写成加号 WA 不停是什么情况)

Source Code

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>

using namespace std;
typedef long long lli;
const int maxn = 5010;

struct player {
    int hei, vel, sum;
} arr[2][maxn];

bool cmp_hei(player a, player b)
    { return a.hei < b.hei; }
bool cmp_sum(player a, player b)
    { return a.sum < b.sum; }
bool check(int __x, int __y, int minn, int maxx)
    { return arr[__x][__y].vel >= minn
        && arr[__x][__y].vel <= maxx; }

int n, A, B, C;

int main(int argc, char** argv)
{
    scanf("%d%d%d%d", &n, &A, &B, &C);
    for (int i = 1; i <= n; i++) {
        scanf("%d%d", &arr[0][i].hei,
            &arr[0][i].vel);
        arr[0][i].sum = A * arr[0][i].hei
            + B * arr[0][i].vel;
        arr[1][i] = arr[0][i];
    }
    sort(arr[0] + 1, arr[0] + 1 + n, cmp_hei);
    sort(arr[1] + 1, arr[1] + 1 + n, cmp_sum);
    // Enumerate the velocity of team members
    int res = 0;
    for (int i = 1; i <= n; i++) {
        int minn = arr[0][i].vel,
            maxx = minn + C / B;
        int l = 0, r = 0, t_res = 0;
        // Enumerate the height of team members
        for (int j = 1; j <= n; j++) {
            int hei = arr[0][j].hei,
                vel = arr[0][i].vel;
            while (r < n && arr[1][r + 1].sum - A * hei - B * vel <= C)
                t_res += check(1, ++r, minn, maxx);
            while (l < n && arr[0][l + 1].hei < hei)
                t_res -= check(0, ++l, minn, maxx);
            // Update final result
            res = max(res, t_res);
        }
    }
    printf("%d\n", res);
    return 0;
}