Processing math: 100%

「凸包」

凸包

Upd10.17

来补坑啦!

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

例题 [CF535E]Tavas and Pashmaks

yi=S1ai+S2bi

那么我们实际上就是要求一对S1,S2使得yi最小。

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

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

那么就把S2缩成1好咯。

柿子变成了yi=Aai+1bi

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

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

代码

复制代码
 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不可能考同一个考点"就打了个二分...

posted @   _xuefeng  阅读(383)  评论(0编辑  收藏  举报
编辑推荐:
· 聊一聊 C#异步 任务延续的三种底层玩法
· 敏捷开发:如何高效开每日站会
· 为什么 .NET8线程池 容易引发线程饥饿
· golang自带的死锁检测并非银弹
· 如何做好软件架构师
阅读排行:
· 欧阳的2024年终总结,迷茫,重生与失业
· Bolt.new 30秒做了一个网站,还能自动部署,难道要吊打 Cursor?
· 史上最全的Cursor IDE教程
· 关于产品设计的思考
· 我的编程之路 2024
点击右上角即可分享
微信分享提示