NOIP2020.9.19模拟spongebob

NOIP2020.9.19模拟spongebob

Description

在这里插入图片描述

Input

输入文件包含 n + 1 行。
第一行一个整数 n,表示咸鱼 A 在这个月参加安保任务的次数。
接下来 n 行,每行两个整数 ai ,bi ,分别为这一次安保任务的两个参数。

Output

输出一行一个实数 y,表示在所有情况下薪水的最低值。
随后系统会将你的输出与答案进行比较,只有当你的输出与答案绝对误差不超过 10^−3 时才能得到

Sample Input

2
1 1
2 -1

Sample Output

1.50

Data Constraint

在这里插入图片描述

Hint

在这里插入图片描述

题解

题意

求min(sigma(|ai*x + bi|))

分析

显然是零点分段,零点的坐标为-a/b,选取的x一定为某个零点,那么每计算一次x的时间是O(n)的。考虑把绝对值拆掉,发现一个ax+b的函数跨过零点就要变号,且a’x+b’为单调函数,可以知道整个函数的解析式。

code

#include<cstdio>
#include<algorithm>
#define abs(x) (x>0?x:-(x))
#define min(x,y) (x<y?x:y)
#define N 300005
int a[N],b[N],p[N],n,suma;
double c[N],sum,ans=1e10;
using namespace std;
bool cmp(int x,int y) {return c[x]<c[y];}
int main(){
	scanf("%d",&n);
	for (int i=1;i<=n;++i) scanf("%d%d",&a[i],&b[i]),c[p[i]=i]=-1.0*b[i]/a[i];
	sort(p+1,p+n+1,cmp);
	for (int i=1;i<=n;++i) sum+=abs(a[i]*c[p[1]]+b[i]),suma-=abs(a[i]);
	ans=sum;
	for (int i=2;i<=n;++i){
		suma+=abs(2*a[p[i-1]]);
		sum+=suma*(c[p[i]]-c[p[i-1]]);
		ans=min(ans,sum);
	}
	printf("%.6f",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值