[Luogu P4165] [BZOJ 1071] [SCOI2007]組隊

洛谷傳送門

BZOJ傳送門

題目描述

NBA每年都有球員選秀環節。通常用速度和身高兩項數據來衡量一個籃球運動員的基本素質。假如一支球隊裏速度最慢的球員速度爲minVminV,身高最矮的球員高度爲minHminH,那麼這支球隊的所有隊員都應該滿足:A×(heightminH)+B×(speedminV)CA × ( height – minH ) + B × ( speed – minV ) \le C 其中AABBCC爲給定的經驗值。這個式子很容易理解,如果一個球隊的球員速度和身高差距太大,會造成配合的不協調。

請問作爲球隊管理層的你,在NN名選秀球員中,最多能有多少名符合條件的候選球員。

輸入輸出格式

輸入格式:

第一行四個數NNAABBCC 下接NN行每行兩個數描述一個球員的heightheightspeedspeed

輸出格式:

最多候選球員數目。

輸入輸出樣例

輸入樣例#1:

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

輸出樣例#1:

4

說明

數據範圍:$ N \le 5000$ ,heightheightspeedspeed不大於1000010000AABBCC在長整型以內。

解題分析

好妙妙的一道題啊…

首先轉化式子: 爲了方便將heightheight記爲hhspeedspeed記爲vv。 那麼有:
Ah+BvAminH+BminV+C Ah+Bv\le AminH+BminV+C
那麼我們固定一維minVminV, 然後從小到大枚舉minHminH, 發現式子右邊單增, 所以把所有球員按Ah+BvAh+Bv排序, 一個一個加入隊列中。 注意合乎條件的球員一定滿足s[minV,minV+CB]s\in[minV, minV+\frac{C}{B}], 否則左邊一定比右邊大。 在這個過程中統計合法的球員個數。

但這樣加進來的球員不一定滿足hHh\ge H的限制, 所以我們把所有球員按hh從小到大排序, 然後逐個pop, 如果遇到vv符合條件的球員, 那麼這個球員一定被統計過了(因爲Ah+BvAh+Bv一定\le當前不等式右邊的值), 直接減去貢獻即可。

總複雜度是O(N2)O(N^2)

代碼如下:

#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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章