【bzoj4570】[Scoi2016]妖怪 凸包
2016-05-20 19:04
459 查看
二分竟然过不去,真可恶。
二分答案,判断每个点是否可行,转换成解二次不等式,在数轴上求交集。
TLE
正解是凸包。
n个点(x,y),在点(x,y)处的斜率为k(k<0)的直线得到的答案为横纵截距之和,即x+y-x*k-y/k
单独使点(x,y)最小,得到的答案为x+y+2*sqrt(xy)
求出这n个点的凸包,最大的答案永远在凸包上,每个点作为最大值都有一个斜率k的取值范围,只需求出每个点在这个区间内的最小值即可。
如果单独使点i最小的同时,也使得点i是所有点的最大值,即斜率-sqrt(y/x)在合法的斜率k区间内,则更新答案。
否则,用上一个点与这一个点的斜率计算答案。
如果不考虑二分的算法,正解还是有一些思维含量的。
UPD:谢谢来自HN的神犇帮忙hack,原来的代码判断k<0,也就是对应到原题中的k>0上
二分答案,判断每个点是否可行,转换成解二次不等式,在数轴上求交集。
TLE
正解是凸包。
n个点(x,y),在点(x,y)处的斜率为k(k<0)的直线得到的答案为横纵截距之和,即x+y-x*k-y/k
单独使点(x,y)最小,得到的答案为x+y+2*sqrt(xy)
求出这n个点的凸包,最大的答案永远在凸包上,每个点作为最大值都有一个斜率k的取值范围,只需求出每个点在这个区间内的最小值即可。
如果单独使点i最小的同时,也使得点i是所有点的最大值,即斜率-sqrt(y/x)在合法的斜率k区间内,则更新答案。
否则,用上一个点与这一个点的斜率计算答案。
如果不考虑二分的算法,正解还是有一些思维含量的。
UPD:谢谢来自HN的神犇帮忙hack,原来的代码判断k<0,也就是对应到原题中的k>0上
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #define maxn 1000100 #define eps 1e-8 using namespace std; struct yts { double x,y; }q[maxn],s[maxn]; yts operator-(yts x,yts y) {return (yts){x.x-y.x,x.y-y.y};} double operator*(yts x,yts y) {return x.x*y.y-x.y*y.x;} double slope(yts x,yts y) {if (x.x==y.x) return -1e60; else return (y.y-x.y)/(y.x-x.x);} double slope(yts x) {return -sqrt(x.y/x.x);} double calc(yts x,double k) {if (k>=0) return 1e20; else return x.x+x.y-x.x*k-x.y/k;} int n,top; double ans; bool cmp(yts x,yts y) { return x.x<y.x || (x.x==y.x && x.y>y.y); } int main() { //freopen("4570.in","r",stdin); scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%lf%lf",&q[i].x,&q[i].y); sort(q+1,q+n+1,cmp); int top=1;s[1]=q[1]; for (int i=2;i<=n;i++) { while (top>1 && (q[i]-s[top])*(s[top]-s[top-1])<0) top--; s[++top]=q[i]; } if (top==1) ans=calc(s[1],slope(s[1])); else { double sp,sp1,sp2; ans=1e20; sp2=slope(s[1],s[2]);sp=slope(s[1]); if (sp>=sp2) ans=min(ans,calc(s[1],sp)); for (int i=2;i<top;i++) { sp1=slope(s[i-1],s[i]);sp2=slope(s[i],s[i+1]);sp=slope(s[i]); ans=min(ans,calc(s[i],sp1)); if (sp1>=sp && sp>=sp2) ans=min(ans,calc(s[i],sp)); } sp1=slope(s[top-1],s[top]);sp=slope(s[top]); ans=min(ans,calc(s[top],sp1)); if (sp<=sp1) ans=min(ans,calc(s[top],sp)); } printf("%.4lf\n",ans); return 0; }
相关文章推荐
- Android Studio上方便使用butterknife注解框架的偷懒插件Android Butterknife Zelezny
- android 应用内页面,截屏监听
- 角色权限数据库设计
- Ajax实现三级联动(0520)
- Android——GridView(显示文字)
- 出差(3~十)
- 237. Delete Node in a (Linked List)
- LightOj 1234(调和级数求和)
- Linux_1_What's shell
- 如何用js控件div的滚动条,让它在内容更新时自动滚到底部?
- RxJava的操作符
- 203. Remove Linked List Elements(Linked List)
- 分享一张架构图
- 分享一张架构图
- linux 学习资料
- 【PS4开发】如何通过unity3d发布ps4应用
- TCP/IP,Http,Socket,XMPP的区别
- Powershell 中直接运行 Python 的文件
- 逆向工具Enjarify [谷歌出品]
- Java30道精选面试题