洛谷傳送門
BZOJ傳送門
題目描述
NBA每年都有球員選秀環節。通常用速度和身高兩項數據來衡量一個籃球運動員的基本素質。假如一支球隊裏速度最慢的球員速度爲,身高最矮的球員高度爲,那麼這支球隊的所有隊員都應該滿足: 其中和,爲給定的經驗值。這個式子很容易理解,如果一個球隊的球員速度和身高差距太大,會造成配合的不協調。
請問作爲球隊管理層的你,在名選秀球員中,最多能有多少名符合條件的候選球員。
輸入輸出格式
輸入格式:
第一行四個數、、、 下接行每行兩個數描述一個球員的和
輸出格式:
最多候選球員數目。
輸入輸出樣例
輸入樣例#1:
4 1 2 10
5 1
3 2
2 3
2 1
輸出樣例#1:
4
說明
數據範圍:$ N \le 5000$ ,和不大於。、、在長整型以內。
解題分析
好妙妙的一道題啊…
首先轉化式子: 爲了方便將記爲, 記爲。 那麼有:
那麼我們固定一維, 然後從小到大枚舉, 發現式子右邊單增, 所以把所有球員按排序, 一個一個加入隊列中。 注意合乎條件的球員一定滿足, 否則左邊一定比右邊大。 在這個過程中統計合法的球員個數。
但這樣加進來的球員不一定滿足的限制, 所以我們把所有球員按從小到大排序, 然後逐個pop, 如果遇到符合條件的球員, 那麼這個球員一定被統計過了(因爲一定當前不等式右邊的值), 直接減去貢獻即可。
總複雜度是。
代碼如下:
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#define R register
#define IN inline
#define ll long long
#define W while
#define gc getchar()
#define MX 5050
template <class T>
IN void in(T &x)
{
x = 0; R char c = gc;
for (; !isdigit(c); c = gc);
for (; isdigit(c); c = gc)
x = (x << 1) + (x << 3) + c - 48;
}
int n, ans;
ll A, B, C, down, up;
struct INFO {ll h, v, s;} dat[2][MX];
IN bool cmph(const INFO &x, const INFO &y) {return x.h < y.h;}
IN bool cmps(const INFO &x, const INFO &y) {return x.s < y.s;}
IN bool calc(R int id, R int pos) {return dat[id][pos].v >= down && dat[id][pos].v <= up;}
int main(void)
{
int h1, h2, cnt;
in(n), in(A), in(B), in(C);
for (R int i = 1; i <= n; ++i)
{
in(dat[0][i].h), in(dat[0][i].v);
dat[0][i].s = A * dat[0][i].h + B * dat[0][i].v;
dat[1][i] = dat[0][i];
}
std::sort(dat[0] + 1, dat[0] + 1 + n, cmph);
std::sort(dat[1] + 1, dat[1] + 1 + n, cmps);
for (R int i = 1; i <= n; ++i)
{
h1 = h2 = cnt = 0;
down = dat[0][i].v, up = dat[0][i].v + C / B;
for (R int j = 1; j <= n; ++j)
{
ll S = C + A * dat[0][j].h + B * down;
W (h1 < n && dat[1][h1 + 1].s <= S) ++h1, cnt += calc(1, h1);
W (h2 < n && dat[0][h2 + 1].h < dat[0][j].h) ++h2, cnt -= calc(0, h2);
ans = std::max(ans, cnt);
}
}
printf("%d\n", ans);
}