• 「凸包」


    凸包

    Upd10.17

    来补坑啦!

    总结一下,我做过的凸包题,好像只有两道。

    上一道现在还没有A(呜呜

    基本的凸包就是一个套路,就是你先化简一个看上去很丑的柿子,然后把它化简成$y=ax+b$的形式

    基本上就是有很多个a与b,那么一般就是求所有直线在同一个x条件下的最大值/最小值。

    那么就成为了静态凸包的基本问题了:静态维护上凸包/下凸包。

    具体的,以下凸包为例。(就做过下凸包,上凸包应该差不多唔

    要维护下凸包,实际上就是找在每个x条件下最靠下边的那一条线。

    我们把所有的直线按照斜率降序排序,为什么呢

    因为我们知道当x趋近正无穷时一定是斜率小的y值小,我们想让这个凸包更加有棱有角

    所以要先把一些不够优秀的直线放到凸包里,希冀它能作出一点贡献

    那么重点来了,如何维护下凸包?

    假如我们现在有一个新加入的直线,我们假设它与栈顶直线的交点横坐标为x1,与栈顶-1直线的交点横坐标为x2.

    考虑到加入的直线的斜率一定是单减的,那么画一下图可以发现(其实是我语文不好)当x1<x2时,栈顶的直线一定不能够构成下凸包

    那么此时就可以把栈顶pop掉了,这样一直做,一直到构成下凸包为止。

    正确性?画画图显然啊(再次黑框)

    例题 [CF535E]Tavas and Pashmaks

    设$y_{i}=frac{S_{1}}{a_{i}}+frac{S_{2}}{b_{i}}$

    那么我们实际上就是要求一对S1,S2使得$y_{i}$最小。

    考虑此时有两个未知数,不好搞,总不能搞三维凸包吧。

    考虑到S1S2的数据范围是一切实数,那么考虑到将S1S2同时缩小倍数关系选手的y关系不变。

    那么就把S2缩成1好咯。

    柿子变成了$y_{i}=frac{A}{a_{i}}+frac{1}{b_{i}}$

    那就好搞咯,静态维护下凸包就好咯。

    入门题。(但是我考试时候屁都不会)

    代码

     1 #include<bits/stdc++.h>
     2 #define lb long double
     3 #define N 600005
     4 using namespace std;
     5 const lb eps=9e-25;
     6 inline int read(){
     7     register int x=0,f=1;char ch=getchar();
     8     while(!isdigit(ch)) f=ch=='-'?-1:1,ch=getchar();
     9     while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-48,ch=getchar();
    10     return x*f;
    11 }
    12 struct node{int a,b,id;}q[N],p[N];
    13 bool operator < (const node &a,const node &b){return a.a!=b.a?a.a<b.a:a.b<b.b;}
    14 int sta[N],top,n;
    15 int v[N];
    16 map<int,int>M;
    17 #define A(x) q[x].a
    18 #define B(x) q[x].b
    19 #define ID(x) q[x].id
    20 long double point(int x,int y){return 1.0L*(B(x)-B(y))*A(x)*A(y)/B(x)/B(y)/(A(y)-A(x));}
    21 int main(){
    22 //    freopen("text.in","r",stdin);
    23     n=read();
    24     for(int i=1;i<=n;++i) A(i)=read(),B(i)=read(),ID(i)=i;
    25 
    26     sort(q+1,q+n+1);int io=0;
    27     for(int i=1;i<=n;++i)
    28         if(A(i)==A(i-1)&&B(i)==B(i-1)&&i!=1) M[ID(i)]=M[ID(i-1)];
    29         else M[ID(i)]=ID(i),p[++io]=q[i];
    30     for(int i=1;i<=io;++i) q[i]=p[i];
    31     for(int i=1;i<=io;++i){ED:bool D=0;
    32         while(top&&A(sta[top])==A(i)) top--,D=1;
    33         while(top>=2&&point(sta[top],i)<point(sta[top-1],i)) top--,D=1;
    34         while(top&&point(sta[top],i)<eps) top--,D=1;
    35         if(D) goto ED;
    36         sta[++top]=i;
    37     }
    38     for(int i=1;i<=top;++i) v[M[ID(sta[i])]]=1;
    39     for(int i=1;i<=n;++i) if(v[M[i]]) printf("%d ",i);
    40     return 0;
    41 }
    这题卡精

     UPD10.25模拟测试

    T1明明是一道傻雕二分答案被我生生肛成了凸包....然后还A了...

     UPD10.26模拟测试

    T1是个凸包我本着“两天T1不可能考同一个考点"就打了个二分...

  • 相关阅读:
    Programming Contest Ranking(题解)
    Alphabet Cookies
    hpu 1267 Cafeteria (01背包)
    Triangles 正多边形分割锐角三角形
    ACdream 1067:Triangles
    hdu 1253 胜利大逃亡 (代码详解)解题报告
    最短路
    POJ- 1511 Invitation Cards
    E
    HDU
  • 原文地址:https://www.cnblogs.com/hzoi2018-xuefeng/p/11690394.html
Copyright © 2020-2023  润新知