國慶七連測(二)多段線性函式
阿新 • • 發佈:2018-12-13
【冗長的題目描述】 目標是使得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;
}