2 条题解
-
0
提供一个 的做法
令第 个人的两部分成绩分别为 和 ,小林则为 和
令 ,则显然有 ,这样我们可以将两个权重简化为一个
排名最高 小林最终成绩比尽可能多的人高(或等于)
若小林成绩高于或等于第 个人:
$$a_1c+b_1(1-c)\geq a_ic+b_i(1-c) \\ (a_1-b_1+b_i-a_i)c\ge b_i-b_1 \\ \left\{\begin{matrix} c\ge \frac{b_i-b_1}{a_1-b_1+b_i-a_i} & a_1-b_1+b_i-a_i>0\\ c\le \frac{b_i-b_1}{a_1-b_1+b_i-a_i} & a_1-b_1+b_i-a_i<0 \\ b_i-b_1\leq 0 & a_1-b_1+b_i-a_i=0 \end{matrix}\right. $$第三种情况(等于零)特判并排除,其余第 个人相当于提供一个值 ,我们所决定的 大于等于或小于等于 便可获得 点价值,并试图令总价值最高。
因此我们将 排序后暴力枚举 处于每个间隔并计算答案即可(枚举 处于每个点同样可行)
代码采用分数排序
#include<bits/stdc++.h> using namespace std; const int inf=0x3f3f3f3f; int n,m; int x,y; int a[5060],b[5060]; struct node { int p,q; bool f; }; node v[5060]; int vl=0; bool cmp(node x,node y) { if(x.p*y.q==y.p*x.q) return x.f>y.f;//避免多个值相同对结果计算的影响 else return x.p*y.q<y.p*x.q; } int l1[5060],r0[5060]; int sum=0; int main() { scanf("%d",&n); m=n; scanf("%d%d",&x,&y); n--; for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]); for(int i=1;i<=n;i++) { int p,q; p=b[i]-y; q=x-y+b[i]-a[i]; if(q>0) v[++vl]=node{p,q,1}; else if(q<0) v[++vl]=node{p,q,0}; else { if(p<=0) sum++;//特判 } } n=vl; for(int i=1;i<=n;i++) { if(v[i].q<0) v[i].q=-v[i].q,v[i].p=-v[i].p; } sort(v+1,v+n+1,cmp); l1[0]=0; r0[n+1]=0; for(int i=1;i<=n;i++) { if(v[i].f) l1[i]=l1[i-1]+1; else l1[i]=l1[i-1]; } for(int i=n;i>=1;i--) { if(!v[i].f) r0[i]=r0[i+1]+1; else r0[i]=r0[i+1]; } int ans=0; v[0].p=-inf; v[0].q=1; v[n+1].p=inf; v[n+1].q=1; for(int i=0;i<=n;i++) //枚举间隔 { if(v[i+1].p<0||v[i].p>v[i].q) continue; ans=max(ans,l1[i]+r0[i+1]); } /* for(int i=1;i<=n;i++) //枚举点 { if(v[i].p<0||v[i].p>v[i].q) continue; ans=max(ans,l1[i]+r0[i]); } */ printf("%d\n",m-(ans+sum)); return 0; }
信息
- ID
- 159
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 666
- 已通过
- 19
- 上传者