2 条题解
-
0
我们很容易得到一个时间复杂度为 的方法:枚举和,然后把所有球员枚举一边,统计可不可以。
那么,如果我们先枚举 ,然后我们可以可以通过这个不等式:
( )+ ( )
得到:
( ( - ))/ )
然后算出每一个球员在 确定的情况下, 在哪一个范围的时候,这个球员可以被选中。
然后我们只要通过差分,然后枚举每一个 找到最大值就可以了。
其余的注释在代码里:(还有,我在代码中把速度用 来表示速度)
#include<bits/stdc++.h> #define int long long using namespace std; const int M=5005; int n,A,B,C,h[M],hh[M],s[M],hs=1,ans=1; int cnt[M*2],smax; signed main() { cin>>n>>A>>B>>C; for (int i=1;i<=n;i++) cin>>h[i]>>s[i],smax=max(smax,s[i]),hh[i]=h[i]; sort(hh+1,hh+1+n); for (int i=2;i<=n;i++) if (hh[i]!=hh[i-1]) hh[++hs]=hh[i];//这一步是把h排序并去重 for (int i=1;i<=hs;i++) { memset(cnt,0,sizeof(cnt)); for (int j=1;j<=n;j++) { if (h[j]>=hh[i]&&(A*(h[j]-hh[i]))<=C) { int tl; if (B==0) tl=1; else tl=max(1ll,s[j]-(C-A*(h[j]-hh[i]))/B); //这说明第j个数当Smin在tl~s[j]中时这个球员都可以被入选 cnt[tl]++,cnt[s[j]+1]--;//差分,做了前缀和之后就相当于把tl~s[j]的数值+1 } } for (int j=2;j<=smax;j++) cnt[j]+=cnt[j-1];//做前缀和 for (int j=1;j<=n;j++) ans=max(ans,cnt[s[j]]);//统计答案 } cout<<ans; return 0; } -
0
原式为:A*(height-minh)+B*(speed-mins)<=C 变换一下可得: height-minh<=[C-B*(speed-mins)]/A; 假设mins确定,那对于每个球员,我们枚举每个minh,求出minh在哪个范围内时,这个球员会被选中,再累加,求出可使结果最大的minh
#include<bits/stdc++.h> using namespace std; const int N=6000; typedef long long ll; ll s[N],h[N],change[N],sum[N*2]; bool v[N*2]; int main(){ int n,a,b,c;scanf("%d%d%d%d",&n,&a,&b,&c); ll maxh=0,len=0; for(int i=1;i<=n;i++){ scanf("%lld%lld",&h[i],&s[i]); maxh=max(maxh,h[i]); if(!v[s[i]])change[++len]=s[i],v[s[i]]=1;//去重,因为对于同一个mins,只需一次计算出最大的答案 } sort(change+1,change+1+len); ll res=1; for(int i=1;i<=len;i++){ for(int j=1;j<=maxh;j++) sum[j]=0; for(int j=1;j<=n;j++){ if(s[j]>=change[i]&&b*(s[j]-change[i])<=c){//当前的mins与当前的球员是否符合条件 ll flag=1; if(a==0) flag=1; else flag=max(flag,h[j]-(c-b*(s[j]-change[i]))/a); sum[flag]++,sum[h[j]+1]--; } } for(int j=1;j<=maxh;j++) sum[j]=sum[j-1]+sum[j]; for(int j=1;j<=n;j++) res=max(res,sum[h[j]]); } printf("%lld",res); }
- 1
信息
- ID
- 2724
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 6
- 标签
- 递交数
- 23
- 已通过
- 11
- 上传者