多段线性函数

题目描述

这里写图片描述

三分大水?

我们容易证明,fmin是一个非严格单峰函数。
对于一个xi,随着y的增大,它的贡献先是一个减量,再是一个为0的常量,最后是一个增量。随着y的增大,fmin的增量应该是增量和减减量和。因为每一个都是由增量变成减量,因此fmin的增量越来越大,所以fmin单峰。因为平板的存在,fmin只能算是非严格单峰函数。
因此我们考虑三分出极值,再二分出取值范围。
三分在有平板的情况下好像是错的?例如在极点右端造一大段平板,那么如果两个三分点都卡在这段平板上,把左端调整会使得我们错过极点。
但是这题三分没有错,为什么?
如果出现了平板,此时fmin的增量就是0。这题fmin的增量是单调的,增量为0说明是一条切线,这个时候平板处一定是极值。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int maxn=100000+10;
int L[maxn],R[maxn];
ll ans;
int i,j,k,l,r,mid,mid1,mid2,t,n,m,mi,mx,ansl,ansr,id;
int read(){
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0'||ch>'9'){
        if (ch=='-') f=-1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
ll f(int x){
    int i;
    ll t=0;
    fo(i,1,n){
        if (L[i]<=x&&x<=R[i]) continue;
        else if (x<L[i]) t+=(ll)(L[i]-x);
        else t+=(ll)(x-R[i]);
    }
    return t;
}
int main(){
    freopen("linear.in","r",stdin);freopen("linear.out","w",stdout);
    n=read();
    mi=2000000000;
    fo(i,1,n) L[i]=read(),R[i]=read(),mi=min(mi,L[i]),mx=max(mx,R[i]);
    l=mi;r=mx;
    while (l<r){
        if (r-l==1){
            if (f(l)>f(r)) l=r;
            break;
        }
        else if (r-l==2){
            mid=(l+r)/2;
            if (f(l)>f(mid)) l=mid;
            if (f(l)>f(r)) l=r;
            break;
        }
        mid1=l+(r-l+1)/3;mid2=l+(r-l+1)/3*2;
        if (f(mid1)<f(mid2)) r=mid2;else l=mid1;
    }
    id=l;
    ans=f(id);
    l=mi;r=id;
    while (l<r){
        mid=(l+r)/2;
        if (f(mid)>ans) l=mid+1;else r=mid;
    }
    ansl=l;
    l=id;r=mx;
    while (l<r){
        mid=(l+r+1)/2;
        if (f(mid)>ans) r=mid-1;else l=mid;
    }
    ansr=l;
    printf("%d %d\n",ansl,ansr);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值