洛谷题目传送门

CF题目传送门

对于这题,我无力吐槽。

虽然式子还是不难想,做法也随便口胡,但是一些鬼畜边界情况就是判不对。

首先显然二分答案。

对于每一个雨滴,它出现的时刻我们的绳子必须落在它上面。把绳子的上下端点用二元组\((a,b)\)表示,因为三个点\((a,0)(x_i,y_i)(b,h)\)共线,我们可以推出

\[(b-a,h)×(x_i-a,y_i)=0\\(h-y_i)a+y_ib-x_ih=0
\]

这说明了\(a,b\)的关系,必须落在一条直线上!它在\((0,0)(0,w)(w,w)(w,0)\)矩形范围内的部分就是可行域。

现在,我们初始的可行域是一个点\((e1,e2)\),到下一个时刻之前,可行域会向四周扩散\(v*\Delta t\)个单位,形成了一个正方形。这个正方形与下一个可行域线段的交,就是当前真正的可行域。那假如当前可行域是一个线段,它扩散是什么样子呢?是一个六边形,等于线段和正方形的闵可夫斯基和。

一个线段和一个凸包的交怎么求呢?我的做法比较蒟蒻,把线段和凸包的交点求出来,按交点个数、端点与凸包的位置关系分类讨论一下。

我们不断地做下去,中途如果出现可行域没有交了就说明不合法。

接下来是实现细节。

首先,对于\(t\)相同的雨滴,我们直接把它们的可行域合并,以免接下来做闵可夫斯基和的时候凸包退化成点或线段。

头疼的就是这里了。合并的时候,要分成线段和线段的交,线段和点的交,点和点的交讨论个半天。因为线段和线段可以直接套SegCross求交点,但是线段和点不能套,会除\(0\)。注意线段平行/重合还要单独拿出来判,不过显然如果重合的话\(x,y\)都是相等的,不然就平行也就是没有交集了,直接cout<<"-1"

再就是特判的时候有些地方非得用EPS,不然过不了。因为值域为整数而且范围只有\(10^3\),所以EPS设大点没关系,小于\(\frac{1}{\text{值域}^2}\)就可以了。

惨痛的教训:强烈建议不要试图将此题作为计算几何板子的练习题,因为光是讨论就不知道比敲板子麻烦到哪里去了。有些丑陋的板子看不懂的话就去踩蒟蒻的总结吧。

#include<bits/stdc++.h>
#define R register int
#define I inline
#define G if(++ip==ie)if(fread(ip=buf,1,SZ,stdin))
using namespace std;
typedef double DB;
const int SZ=1<<19,N=1e5+9;
const DB EPS=1e-8;
char buf[SZ],*ie=buf+SZ,*ip=ie-1;
inline int in(){
G;while(*ip<'-')G;
R x=*ip&15;G;
while(*ip>'-'){x*=10;x+=*ip&15;G;}
return x;
}
inline bool is0(DB x){return fabs(x)<EPS;}
struct Vec{
DB x,y;
I Vec(){x=y=0;}
I Vec(DB a){x=a;y=0;}
I Vec(DB a,DB b){x=a;y=b;}
I friend istream&operator>>(istream&cin,Vec&a){return a.x=in(),a.y=in(),cin;}
I Vec operator-(){return Vec(-x,-y);}
I Vec operator+(Vec a){return Vec(x+a.x,y+a.y);}
I Vec operator-(Vec a){return Vec(x-a.x,y-a.y);}
I Vec operator*(DB a){return Vec(x*a,y*a);}
I Vec operator/(DB a){return Vec(x/a,y/a);}
I friend Vec operator*(DB a,Vec b){b.x*=a,b.y*=a;return b;}
I Vec&operator+=(Vec a){x+=a.x,y+=a.y;return*this;}
I Vec&operator-=(Vec a){x-=a.x,y-=a.y;return*this;}
I DB operator*(Vec a){return x*a.x+y*a.y;}
I DB operator^(Vec a){return x*a.y-y*a.x;}
I bool operator==(Vec a){return is0(x-a.x)&&is0(y-a.y);}
I friend bool operator<(Vec a,Vec b){
return (a^b)>0||(is0(a^b)&&Len(a)<Len(b));
}
I friend DB Len(Vec a){
return sqrt(a.x*a.x+a.y*a.y);
}
}a[N],b[N],c[9],d[9],e;
int t[N],st[N];
I Vec LineCross(Vec a1,Vec a2,Vec b1,Vec b2){
a2-=a1;b2-=b1;
return b2^a2?a1+(b2^(b1-a1))/(b2^a2)*a2:Vec(NAN,NAN);
}
I Vec SegCross(Vec&a1,Vec&a2,Vec&b1,Vec&b2){
Vec c=LineCross(a1,a2,b1,b2);
return (a1-c)*(a2-c)>EPS||(b1-c)*(b2-c)>EPS?Vec(NAN,NAN):c;
}
I int Convex(Vec*a,R n){
R k=0,p=0;Vec bs;
for(R i=1;i<n;++i)
if(a[i].y<a[k].y||(a[i].y==a[k].y&&a[i].x<a[k].x))k=i;
swap(a[0],a[k]);bs=a[0];
for(R i=0;i<n;++i)a[i]-=bs;
sort(a+1,a+n);
for(R i=1;i<n;st[++p]=i++)
while(p&&((a[i]-a[st[p-1]])^(a[st[p]]-a[st[p-1]]))>-EPS)--p;
for(R i=0;i<=p;++i)a[i]=a[st[i]]+bs;
return a[p+1]=bs,p+1;
}
I int Minkowski(Vec*a,R n,DB t){
for(R i=n-1,j=4*n;j;--i){
a[--j]=a[i]+Vec(-t,-t);
a[--j]=a[i]+Vec( t,-t);
a[--j]=a[i]+Vec( t, t);
a[--j]=a[i]+Vec(-t, t);
}
return Convex(a,4*n);
}
I bool Inside(Vec*a,R n,Vec v){//点是否在凸包内
for(R i=0;i<n;++i)
if(((a[i+1]-a[i])^(v-a[i]))<-EPS)return 0;
return 1;
}
I bool Check(R q,DB mid){
R n=1,p;
c[0]=e;
for(R i=1;i<=q;++i){
n=Minkowski(c,n,(t[i]-t[i-1])*mid);
for(R j=p=0;j<n;++j){//搞出所有交点,注意去重
d[p]=SegCross(a[i],b[i],c[j],c[j+1]);
p+=!(isnan(d[p].x)||(p&&d[p-1]==d[p]));
}
if(p==0){//更新当前可行域,讨论开始
if(!Inside(c,n,a[i]))return 0;
c[0]=a[i],c[1]=b[i];
}
else if(p==1){
if(Inside(c,n,a[i]))
c[1]=Inside(c,n,b[i])?(d[0]==b[i]?a[i]:b[i]):a[i];
else c[1]=Inside(c,n,b[i])?b[i]:d[0];
c[0]=d[0];
}
else c[0]=d[0],c[1]=d[1];//讨论结束
n=1+!(c[0]==c[1]);
}
return 1;
}
I void Err(bool f){if(f)cout<<"-1\n",exit(0);}
int main(){
ios::sync_with_stdio(0);
R n=in(),q=0,w=in(),h=in(),lx=0,ly=0;
cin>>e;
for(R i=1;i<=n;++i){
R tt=in(),x=in(),y=in();
Vec u=0,v=0;//求可行域线段,讨论开始
if((u.x=(DB)x*h/(h-y))>w)u=Vec(w,(DB)(x*h-(h-y)*w)/y);
if((v.y=(DB)x*h/y )>w)v=Vec((DB)(x*h-y*w)/(h-y),w);//讨论结束
if(tt!=t[q])++q,a[q]=u,b[q]=v;//合并t相同的可行域,讨论开始
else if(a[q]==b[q]){
if(u==v)Err(!(u==a[q]));//点交点
else Err(!is0((u-a[q])^(v-a[q])));//点交线段
}
else if(x!=lx||y!=ly){
if(u==v)Err(!is0((u-a[q])^(u-b[q])));//点交线段
else Err(isnan((u=SegCross(a[q],b[q],u,v)).x));//线段交线段
a[q]=b[q]=u;
}//讨论结束
t[q]=tt;lx=x;ly=y;
}
DB l=0,r=w,mid;
while((r-l)/max(1.0,l)>1e-4)
mid=(l+r)/2,(Check(q,mid)?r:l)=mid;
cout<<fixed<<setprecision(6)<<(l+r)/2<<'\n';
return 0;
}

洛谷CF1071E Rain Protection(计算几何,闵可夫斯基和,凸包,二分答案)的更多相关文章

  1. 洛谷P1084 疫情控制(NOIP2012)(二分答案,贪心,树形DP)

    洛谷题目传送门 费了几个小时杠掉此题,如果不是那水水的数据的话,跟列队的难度真的是有得一比... 话说蒟蒻仔细翻了所有的题解,发现巨佬写的都是倍增,复杂度是\(O(n\log n\log nw)\)的 ...

  2. 洛谷P4557 [JSOI2018]战争(闵可夫斯基和+凸包)

    题面 传送门 题解 看出这是个闵可夫斯基和了然而我当初因为见到这词汇是在\(shadowice\)巨巨的\(Ynoi\)题解里所以压根没敢学-- 首先您需要知道这个 首先如果有一个向量\(w\)使得\ ...

  3. 洛谷P1084 疫情控制 [noip2012] 贪心+树论+二分答案 (还有个小bugQAQ

    正解:贪心+倍增+二分答案 解题报告: 正好想做noip的题目然后又想落实学长之前讲的题?于是就找上了这题 其实之前做过,70,然后实在细节太多太复杂就不了了之,现在再看一遍感觉又一脸懵了... 从标 ...

  4. 洛谷P2680 运输计划(倍增LCA + 树上差分 + 二分答案)

    [题目链接] [思路]: 根据题意可以明显看出,当所有任务都完成时的时间是最终的结果,也就是说本题要求,求出最小的最大值. 那这样的话就暗示了将答案二分,进行check. [check方法]: 如果说 ...

  5. 洛谷 P1948 [USACO08JAN]电话线Telephone Lines 最短路+二分答案

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例 输出样例 说明 思路 AC代码 题面 题目链接 P1948 [USACO08JAN]电话线Telephone ...

  6. 洛谷P1462 通往奥格瑞玛的道路 题解 最短路+二分答案

    题目链接:https://www.luogu.com.cn/problem/P1462 题目大意: 有 \(n\) 个点 \(m\) 条边,每个点有一个点权,每个边有一个边权.求所有长度不超过 \(b ...

  7. 【BZOJ4009_洛谷3242】[HNOI2015] 接水果(整体二分)

    题目: 洛谷 3242 分析: 明确题意:在一棵树上给定若干权值为 \(w\) 的路径 \((u,v)\) (盘子),每次给定 \((a,b)\) (水果),询问所有满足 \((u,v)\) 被 \( ...

  8. 【洛谷P1823】音乐会的等待 单调栈+二分

    题目大意:给定一个长度为 N 的序列,定义两个数 \(a[i],a[j]\) 相互看得见,意味着 \(\forall k\in [i+1,j-1],a[k]\le a[i],a[k]\le a[j]\ ...

  9. 洛谷P4027 [NOI2007]货币兑换(dp 斜率优化 cdq 二分)

    题意 题目链接 Sol 解题的关键是看到题目里的提示... 设\(f[i]\)表示到第\(i\)天所持有软妹币的最大数量,显然答案为\(max_{i = 1}^n f[i]\) 转移为\(f_i = ...

随机推荐

  1. (第十三周)Final阶段用户调查报告

    项目名:食物链教学工具 组名:奋斗吧兄弟 组长:黄兴 组员:李俞寰.杜桥.栾骄阳.王东涵 用户调查报告 调查时间:2016年12月1日  21:00——2016年12月3日  12:00 项目分享链接 ...

  2. MySQLl导入导出SQL文件

    window 1.导出整个数据库 mysqldump -u 用户名 -p 数据库名 > 导出的文件名 mysqldump -u dbuser -p dbname > dbname.sql ...

  3. rest-framework解析器,url控制,分页,响应器,渲染器,版本控制

    解析器 1.json解析器 发一个json格式的post请求.后台打印: request_data---> {'title': '北京折叠'} request.POST---> <Q ...

  4. PAT 7-12 拯救007

    在老电影“007之生死关头”(Live and Let Die)中有一个情节,007被毒贩抓到一个鳄鱼池中心的小岛上,他用了一种极为大胆的方法逃脱 —— 直接踩着池子里一系列鳄鱼的大脑袋跳上岸去!(据 ...

  5. JEECG 3.7 Memory Leak

    JEECG 3.7 版本常见问题贴 - JEECG官方网站-企业级JAVA快速开发平台 - Powered by Discuz!http://www.jeecg.org/forum.php?mod=v ...

  6. 网站之.htaccess文件

    Apache系统中的.htaccess文件(分布式配置文件)提供了针对目录改变配置的方法,也就是在一个特定的文件目录中放置一个包含指令的文件,以作用于此目录以及所有子目录.直白的说,.htaccess ...

  7. Mysql中的排序规则utf8_unicode_ci、utf8_general_ci总结

    Mysql中utf8_general_ci与utf8_unicode_ci有什么区别呢?在编程语言中,通常用unicode对中文字符做处理,防止出现乱码,那么在MySQL里,为什么大家都使用utf8_ ...

  8. 【Python3练习题 016】 猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个。第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。求第一天共摘了多少。

    这题得倒着推.第10天还没吃,就剩1个,说明第9天吃完一半再吃1个还剩1个,假设第9天还没吃之前有桃子p个,可得:p * 1/2 - 1 = 1,可得 p = 4.以此类推,即可手算出. 代码思路为: ...

  9. day 7-19 Mysql索引原理与查询优化

    一,介绍 1.什么是索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语 ...

  10. hashCode和equals的关系分析

    hashCode:说白了,简单的就看做一个函数,但是该函数有可能出现:对于某个x值,存在不止一个y值与之对应.这种情况就叫哈希碰撞. 那么: 1.如果hashCode相等,两个对象不一定是同一个对象( ...