说是半平面交,实际上只是维护了个下凸壳而已……同1007水平可见直线

  对于每条线段,能看到这条线段的点都在这条线段的“上方”,那么对所有n-1条线段求一个可视区域的交,就是求一个半平面交……(好扯)

  一开始我想的是:直接找到这个下凸壳的最低点,它的y值就是答案辣~但是明显不对>_>这题让求的是塔的最低高度……不光要考虑塔顶,还要看塔底的啊!

  那么我们怎么找呢?我们可以发现:随着x的变化,塔高(就是地面到凸壳的竖直距离,y坐标之差)是一个分段函数,分段点就是地面的折点以及凸壳的顶点!而且在每一段里面,塔高的值是一个一次函数!经过大胆猜想,小(bu)心(yong)证明我们发现:分段一次函数的极值在分段点和边界点处取到。

  那么就是对这些点算一下答案就可以了……点数是O(n)的……

 1 /**************************************************************
 2     Problem: 1038
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:0 ms
 7     Memory:1292 kb
 8 ****************************************************************/
 9  
10 //BZOJ 1038
11 #include<cmath>
12 #include<vector>
13 #include<cstdio>
14 #include<cstring>
15 #include<cstdlib>
16 #include<iostream>
17 #include<algorithm>
18 #define rep(i,n) for(int i=0;i<n;++i)
19 #define F(i,j,n) for(int i=j;i<=n;++i)
20 #define D(i,j,n) for(int i=j;i>=n;--i)
21 #define pb push_back
22 using namespace std;
23 inline int getint(){
24     int v=0,sign=1; char ch=getchar();
25     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
26     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
27     return v*sign;
28 }
29 const int N=310,INF=~0u>>2;
30 typedef long long LL;
31 typedef double lf;
32 const lf eps=1e-8;
33 /******************tamplate*********************/
34 struct Point{
35     lf x,y;
36     void read(){scanf("%lf%lf",&x,&y);}
37 }p[N];
38 struct Line{double k,b;}l[N],st[N];
39 Line make_line(Point a,Point b){
40     Line tmp;
41     tmp.k=(a.y-b.y)/(a.x-b.x);
42     tmp.b=a.y-tmp.k*a.x;
43     return tmp;
44 }
45 int n,top;
46 inline bool cmp(Line a,Line b){
47     if (fabs(a.k-b.k)<eps) return a.b<b.b;
48     return a.k<b.k;
49 }
50 double crossx(Line x1,Line x2){
51     return (x2.b-x1.b)/(x1.k-x2.k);
52 }
53 void insert(Line a){
54     while(top){
55         if (fabs(st[top].k-a.k)<eps) top--;
56         else if (top>1 && crossx(a,st[top-1])<=
57                           crossx(st[top],st[top-1])) top--;
58         else break;
59     }
60     st[++top]=a;
61 }
62 lf Up(lf x){
63     lf ans=0.0;
64     F(i,1,top)
65         ans=max(ans,st[i].k*x+st[i].b);
66     return ans;
67 }
68 lf Down(lf x){
69     int pos;
70     for(pos=1;pos<n && p[pos+1].x<x;pos++);
71     if (pos==n) return -1e10;
72     Line tmp=make_line(p[pos],p[pos+1]);
73     return tmp.k*x+tmp.b;
74 }
75  
76 int main(){
77 #ifndef ONLINE_JUDGE
78     freopen("1038.in","r",stdin);
79     freopen("1038.out","w",stdout);
80 #endif
81     n=getint();
82     F(i,1,n) scanf("%lf",&p[i].x);
83     F(i,1,n) scanf("%lf",&p[i].y);
84     F(i,1,n-1) l[i]=make_line(p[i+1],p[i]);
85     sort(l+1,l+n,cmp);
86     F(i,1,n-1) insert(l[i]);
87     lf ans=1e10;
88     F(i,1,n) ans=min(ans,Up(p[i].x)-p[i].y);
89     F(i,2,top){
90         Point p;
91         p.x=crossx(st[i-1],st[i]);
92         p.y=st[i].k*p.x+st[i].b;
93         ans=min(ans,p.y-Down(p.x));
94     }
95     printf("%.3lf\n",ans);
96     return 0;
97 }
View Code

相关文章:

  • 2021-10-07
  • 2021-05-16
  • 2022-01-20
  • 2022-02-26
  • 2021-06-17
  • 2021-09-08
  • 2021-10-18
猜你喜欢
  • 2021-10-08
  • 2021-11-01
  • 2021-06-03
  • 2021-07-11
  • 2021-10-02
  • 2021-11-02
  • 2021-07-22
相关资源
相似解决方案