2 条题解

  • 0
    @ 2025-8-13 18:19:24

    提供一个 O(nlogn)O(n\log n) 的做法

    令第 ii 个人的两部分成绩分别为 aia_ibib_i,小林则为 a1a_1b1b_1

    c1=cc_1=c,则显然有 c2=1cc_2=1-c,这样我们可以将两个权重简化为一个

    排名最高 \Leftrightarrow 小林最终成绩比尽可能多的人高(或等于)

    若小林成绩高于或等于第 ii 个人:

    $$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. $$

    第三种情况(等于零)特判并排除,其余第 ii 个人相当于提供一个值 vi=bib1a1b1+biaiv_i = \frac{b_i-b_1}{a_1-b_1+b_i-a_i},我们所决定的 cc 大于等于或小于等于 viv_i 便可获得 11 点价值,并试图令总价值最高。

    因此我们将 viv_i 排序后暴力枚举 cc 处于每个间隔并计算答案即可(枚举 cc 处于每个点同样可行)

    代码采用分数排序

    #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
    上传者