国庆七连测(二)多段线性函数

31 篇文章 0 订阅
15 篇文章 0 订阅

【冗长的题目描述】
冗長的題目描述
目标是使得f(y)尽可能的小,并求出y的取值范围。
【算法1】
根据数学证明,f(y)应该是成u形或者平底锅形,所以二分或者三分求“谷底”就可以了。
复杂度为O(n* log2n)
【算法2】
rt,我们考虑多段的线性函数。对于每一个绝对值函数。y<li时,等于-y+li;li<=y<=ri时,(最小)等于0;y>ri时,等于yi-ri;
将这n个函数合并,我们就可以得到一个新的一次函数,求得最小值。
顺序上我们可以按每个点的位置从小到大排序,经过某个点时,改变所在绝对值函数的表达式。
sort+n=O(n* log2n)

Code:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define int long long
using namespace std;
const int maxn=1e5+1000;
int minn,n,L,R;
int zt[maxn],l[maxn],r[maxn];
int k,b,now,t;
struct node{
	int pos,id; 
}lsh[maxn<<1];int cnt;
bool cmp(node x,node y){
	return x.pos<y.pos;
}
signed main(){
	freopen("linear.in","r",stdin);
	freopen("linear.out","w",stdout);
	cin>>n;k=-n;
	for(int i=1;i<=n;i++){
		scanf("%d%d",&l[i],&r[i]);
		lsh[++cnt]=(node){l[i],i},lsh[++cnt]=(node){r[i],i};
		b+=l[i];zt[i]=1;
	}
	sort(lsh+1,lsh+cnt+1,cmp);lsh[cnt+1].pos=1<<30;
	now=lsh[1].pos,t=1;
	minn=k*now+b,L=now,R=now;
	while(t<=cnt){
		do{
			zt[lsh[t].id]++;
			if(zt[lsh[t].id]==2) k++,b-=l[lsh[t].id];
			else k++,b-=r[lsh[t].id];
			t++;
		}while(lsh[t].pos==now);
		now=lsh[t].pos;
		if(k<0){
			if(minn>k*now+b)
				minn=k*now+b,L=now,R=now;
		}
		else if(k==0){
			if(k*now+b==minn) R=now;
		}
	}
	printf("%d %d\n",L,R);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值