1. 程式人生 > >國慶七連測(二)多段線性函式

國慶七連測(二)多段線性函式

【冗長的題目描述】 冗長的題目描述 目標是使得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; }