死国矣…
v v v表示速度, h h h表示高度, s = A h + B v s=Ah+Bv s=Ah+Bv,约束条件化为 A h + B v ≤ C + A m i n h + B m i n v Ah+Bv \leq C+Aminh+Bminv Ah+Bv≤C+Aminh+Bminv
搞两个数组, a a a按照 h h h从小到大排序, b b b按照 s s s从小到大排序。
任意顺序枚举 m i n v minv minv,开两个指针 l l l和 r r r,分别指着 a a a和 b b b的开头。
按照递增的顺序枚举 m i n h minh minh。
如果 b ( r ) s ≤ C + A m i n h + B m i n v b(r)_s \leq C+Aminh+Bminv b(r)s≤C+Aminh+Bminv,就将 r r r指针后移。如果 m i n v ≤ b ( r ) v ≤ C B + m i n v minv \leq b(r)_v \leq \frac{C}{B}+minv minv≤b(r)v≤BC+minv(这个 r r r是移动前的),就令当前统计的球员数量++
如果 a ( l ) h < m i n h a(l)_h < minh a(l)h<minh,则将 l l l指针左移,并在左移前判断如果 m i n v ≤ a ( l ) v ≤ C B + m i n v minv \leq a(l)_v \leq \frac{C}{B}+minv minv≤a(l)v≤BC+minv
你可能会说, m i n v ≤ v minv \leq v minv≤v这个条件没问题,但是为什么一定要 v ≤ C B + m i n v v \leq \frac{C}{B}+minv v≤BC+minv呢?
首先,若 v ≤ C B + m i n v v \leq \frac{C}{B}+minv v≤BC+minv,则 B ( v − m i n v ) ≤ C B(v-minv) \leq C B(v−minv)≤C,对任意一个 h < m i n h h<minh h<minh,都有 A ( h − m i n h ) + B ( v − m i n v ) ≤ C A(h-minh)+B(v-minv) \leq C A(h−minh)+B(v−minv)≤C,我们不会减掉没有出现过的答案。
那为什么不在去除答案的时候判断 s ≤ C + A m i n h + B m i n v s \leq C+Aminh+Bminv s≤C+Aminh+Bminv呢?因为可能你移到某个 l l l时,依然 a ( l ) s > A m i n h + B m i n v + C a(l)_s > Aminh+Bminv+C a(l)s>Aminh+Bminv+C但 a ( l ) h < m i n h a(l)_h < minh a(l)h<minh,于是就没有减去贡献,就会使算出来的答案偏大。
#include<bits/stdc++.h>
using namespace std;
#define RI register int
const int N=5005;
int n,A,B,C,ans;
struct node{int v,h,s;}a[N],b[N];
bool cmp1(node x,node y) {return x.h<y.h;}
bool cmp2(node x,node y) {return x.s<y.s;}
int main()
{
scanf("%d%d%d%d",&n,&A,&B,&C);
for(RI i=1;i<=n;++i) {
scanf("%d%d",&a[i].h,&a[i].v);
a[i].s=A*a[i].h+B*a[i].v,b[i]=a[i];
}
sort(a+1,a+1+n,cmp1),sort(b+1,b+1+n,cmp2);
for(RI i=1;i<=n;++i) {
int minv=a[i].v,l=1,r=1,js=0;
for(RI j=1;j<=n;++j) {
int minh=a[j].h;
while(r<=n&&b[r].s<=A*minh+B*minv+C) {
if(b[r].v>=minv&&b[r].v<=C/B+minv) ++js;
++r;
}
while(l<=n&&a[l].h<minh) {
if(a[l].v>=minv&&a[l].v<=C/B+minv) --js;
++l;
}
ans=max(ans,js);
}
}
printf("%d\n",ans);
return 0;
}