BUPT 2022 Summer Training #2(2018-2019 ACM-ICPC, Asia Seoul Regional Contest)
作者:互联网
E-LED
题目大意:已知N个点(vi,li),求一个分段函数使得这些点在这个函数上的误差的最大值最小。
数据范围:1≤N≤300000,0≤vi,li≤1e9;
解题思路:二分贪心。
二分答案后尽量将排序后的数据归到L1,接着再放到L2,不能放了就是答案无效。
这题的坑在于v=0这个点L0一定为0,还有L1≤L2,所以对于可行解还要比较一下前者最小值和后者最大值的关系。
赛后总结:还算简单的二分,没过的原因主要是这题太晚开了,下次可以经常看看榜单有没有突然比较多人过的题目。
代码如下:
#include<bits/stdc++.h> using namespace std; long long n; struct tu{ long long x,y; }e[300300]; double l=0,r=10000000009,ans; bool cmp(tu a,tu b) { return a.x<b.x; } int main() { cin>>n; for(long long i=1;i<=n;i++) { scanf("%lld%lld",&e[i].x,&e[i].y); } sort(e+1,e+1+n,cmp); while(l<=r) { double mid=(l+r)/2.0; bool flag=1; long long tag=0; double min1=-1,max1=-1,pre=0; for(long long i=1;i<=n;i++) { if(e[i].x==0) { if(e[i].y>mid) { flag=0; break; } else continue; } if(min1<0) { if(e[i].y>mid) { min1=max1=e[i].y; } else continue; } else { double pre_max=max1; min1=min(min1,(double)e[i].y); max1=max(max1,(double)e[i].y); if((max1-min1)>mid*2) { tag++; if(tag==1) { pre=pre_max-mid; } if(tag==2) { flag=0; break; } max1=min1=e[i].y; } } } if(!flag||(pre>min1+mid&&pre!=0)) { l=mid+0.01; } else { r=mid-0.01; ans=mid; } } printf("%0.1lf",round(ans*10)/10.0); return 0; }
标签:pre,Summer,Training,max1,Regional,mid,long,else,min1 来源: https://www.cnblogs.com/hongyubin/p/16479669.html