计算几何相关

news/2025/1/20 19:48:43/文章来源:https://www.cnblogs.com/Claimo0611/p/18682429

扫描线

扫描线直接照搬了...这篇主要是给之后的积分和凸包之类留的。

就是用线段树解决计算几何问题。

板梯

如何处理平面内一群矩形的面积交?

考虑用面积的朴素定义,\(S=ab\),相当于一堆面积合到一起就是 \(b\) 个可以不同的 \(a\) 相加。

我们维护坐标系的 \(x\) 值,再去跳 \(y\) 轴。具体地,只有一个矩形的下边界和上边界才会对当前 \(x\),也就是 \(a\) 值之和造成影响。我们记录一下矩形的上下底面,在下底面 \(y\) 值加上它覆盖的 \(x\) 段,在它的上底面减去它的 \(x\) 段,按照 \(y\) 给这些操作排序后去跳 \(y\),该加加改减减。线段树维护当前 \(y\) 内的 \(x\) 之和,相当于会形成很多的长度段,一堆叠在一起也算一个,瞎搞一下维护即可,\(S=\sum \Delta y*x_i\)

放个代码方便复习。

#include<bits/stdc++.h>
#define MAXN 1000005
#define int long long
using namespace std;
int n;
struct node{int x1,x2,y;int opt;
}sq[MAXN<<1];
inline bool cmp(node a,node b){if(a.y==b.y)return a.opt>b.opt;return a.y<b.y;
}
int mp[MAXN<<2];
int ans,tmp;
struct Segment_Tree{#define ls(p) p<<1#define rs(p) p<<1|1struct TREE{int l,r;int val,tag;//维护一个当前x段的覆盖层数和贡献,只要有层数就有贡献,没层数就没贡献}tree[MAXN<<3];inline void build(int l,int r,int p){tree[p].l=l,tree[p].r=r,tree[p].val=tree[p].tag=0;if(l==r)return;int mid=l+r>>1;build(l,mid,ls(p));build(mid+1,r,rs(p));}inline void push_up(int p){//主要看看pushup即可if(tree[p].tag)tree[p].val=mp[tree[p].r+1]-mp[tree[p].l];else{tree[p].val=tree[ls(p)].val+tree[rs(p)].val;}}inline void modify(int l,int r,int k,int p){if(mp[tree[p].r+1]<=l||mp[tree[p].l]>=r)return;if(mp[tree[p].l]>=l&&mp[tree[p].r+1]<=r){tree[p].tag+=k;push_up(p);return;}//	printf("nowmid=%lld,id=%lld,tree.l=%lld,tree.r=%lld\n",mid,p,tree[p].l,tree[p].r);modify(l,r,k,ls(p));modify(l,r,k,rs(p));push_up(p);}
}ST;
signed main(){scanf("%lld",&n);for(int i=1,x1,x2,y1,y2;i<=n;i++){scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);sq[i]=(node){x1,x2,y1,1};sq[i+n]=(node){x1,x2,y2,-1};mp[i]=x1,mp[i+n]=x2;}sort(mp+1,mp+1+n*2);tmp=unique(mp+1,mp+1+2*n)-mp-1;//printf("tmp=%lld\n",tmp);sort(sq+1,sq+1+n*2,cmp);ST.build(1,tmp-1,1);//printf("ced\n");for(int i=1;i<n*2;i++){//	printf("solving %lld %lld %lldf\n",sq[i].x1,sq[i].x2,sq[i].opt);ST.modify(sq[i].x1,sq[i].x2,sq[i].opt,1);ans+=ST.tree[1].val*(sq[i+1].y-sq[i].y);}printf("%lld",ans);return 0;
}

计算周长

现在让你计算那坨矩形的周长。

同样的分析方法,矩形的下底面和上底面都会对当前答案做出贡献,但是贡献是 \(\Delta x\),相当于新增的或新减少 x 的才是当前 \(y\)\(x\) 贡献,自己画个图想去。

然后考虑竖条对答案的贡献,当前线段树覆盖的一堆线段会形成许多个分开的块,具象下来就是当前 \(y\) 区段实际参与计算的矩形个数。

像是这张图虽然有三个矩形但只形成了两个块,因此实际的竖条个数是当前块数(2)乘以2。

用线段树再维护一下当前区段是否充满就可以推出来一共有几个块,满了就不加,不满就块数相加。

一道好玩的题

考虑用扫描线解决。

用矩形框点太蛋疼了,把点变成框那么大的矩形再用扫描线处理。

每个矩形相当于可以提供它权值的贡献,把这些贡献在 \(x\) 上叠加,发现线段树的极值就是当前 \(y\) 窗口能覆盖到的最大星星权值。没了。

自适应辛普森积分

挺简单的。

暴力展开一个二次函数的积分形式。

\[f(x)=ax^2+bx+c \]

\[\int_l^rf(x)dx=(r-l)(f(l)+4f(\frac{l+r}{2})+f(r))/6 \]

考虑这样一件事,对于一个要求积的函数 \(F(x)\),递归直到和这个二次函数拟合后停止后汇总即可求得一个大概的积分,这就是辛普森法,然而缺点是像保证正确性就会特别慢,想跑快点就要牺牲正确性。

所以提出了自适应辛普森积分,因为对于整个函数肯定有长得比较像二次函数的和长得不太像二次函数的。对于长得像二次函数的可以少递归几次保证复杂度,长得不像的就多递归几次保证正确性。所以分治地进行这个过程,因为二次函数劈两半还是二次函数,对于当前要处理的区间 \([l,r]\) 与把它当作二次函数得到的积分值 \(ans\),如果劈成两半 \([l,mid]\)\([mid,r]\) 分开当二次函数求得的积分值之和 \(\sum\) 已经和 \(ans\) 十分接近了就说明这一段 \([l,r]\) 肯定是很像二次函数了,那就不递归了。反之,因为递归求解下去肯定不会丢失精度,重复上述过程直到拟合为止即可。

另外有一些正确性和复杂度上的优化。比如可以考虑钦定一个无论如何都要达到的递归层数 \(dep\) 来保证不丢精度,或者更改“十分接近”的定义即当前区间的 \(eps\) 来提速或者增加精度,还可以在递归之前扫一遍区间,直接跳过函数中可能存在的大片没有值的段来同时优化时间和正确性。

附上 板子 代码

#include<bits/stdc++.h>
#define db double
using namespace std;
db a,b,c,d,L,R;
const db eps=1e-7;
inline db f(db x){return (c*x+d)/(a*x+b);
}
inline db calc(db l,db r){db mid=(l+r)/2;return (r-l)*(f(l)+4*f(mid)+f(r))/6;
}
inline db asr(db l,db r,db eps,db ans){
//	printf("nowlr=%.5f %.5f\n",l,r);db mid=(l+r)/2.0;db lv=calc(l,mid),rv=calc(mid,r);if(fabs(lv+rv-ans)<=15*eps)return lv+rv+(lv+rv-ans)/15;else return asr(l,mid,eps/2,lv)+asr(mid,r,eps/2,rv);
}
signed main(){scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&L,&R);printf("%.6f\n",asr(L,R,eps,calc(L,R)));return 0;
}

三角形面积并

考虑一种类似扫描线的思路,设 \(F(x_0)\) 为坐标系内 \(x=x_0\) 这条竖线所截的图形段长度,这个可以 \(O(n)\) 扫一遍解出来一堆 \((y_s,y_e)\) 然后排序贪心 \(O(nlogn)\) 求和求出,然后答案即为

\[\int_{minX}^{maxX}F(x)dx \]

圆的面积并

一样的,随便写写就过了。

月下柠檬树

一样的,随便写写就过了。

但是毕竟是道黑是吧所以还是稍微记一下。

脑玩一下发现影子拍上去圆面积不变只有 \(x\) 坐标变了,投影则是若干个圆和相邻圆的两个外公切线(如果有的话)的并形式。

仍然积分法求,对于当前递归到而要求的 \(f(x_0)\),先扫一遍包含那条线的圆能给的贡献(就是上一道题),然后看公切线怎么处理,草稿纸上划一下比如 \(\odot O_1\)\(\odot O_2\) 圆心距为 \(x\) 则公切线所连半径和连心线夹角 \(\alpha\) 应有 \(cos\alpha=\frac{r_1-r_2}{x}\),正弦直接拿1减然后就能表示出公切点的坐标了,判一下有没有穿过 \(x_0\) 然后就是三角形面积并的做法,弄完贡献直接取max就行了。

(未开工)凸包

学到再说。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/872301.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

树状数组(学习笔记)

例题一:P3374 【模板】树状数组 1 例题二:P3368 【模板】树状数组 2 作用:特征: 一个多用于区间修改,和单点查询。或区间查询单点修改的数据结构,其代码量较少,比较好写。 区别: 它与线段树的功能差不多,但线段树的可拓展性更强。也就是说:树状数组能做的,线段树都能…

Centos根目录扩容

CentOS磁盘在根目录下扩容(无卷组情况下)查看磁盘分区情况,sda3挂载在根目录下,新扩容增加的sda4挂在在/data下现在想把sda4同样挂载在根目录下解决方法:删除sda3,再重建sda3(注意:删除后不要退出,紧接着重建,注意重建后的起始位置) 删除sda3然后重建输入下面那个命…

U455764 The Rotation Game

U455764 The Rotation Game 题目理解 本题要求移动\(A-H\)中的一列或一行,使其整个一行和一列的数字移动,使最后的中间8个的数字相同。求最少需要移动的步数和它的操纵顺序思路 1.本题可以很显然的想到用 \(BFS\) 来枚举执行不同字母操作后结果,但每 \(BFS\) 一次就会增加八…

BUU SQL COURSE 2

BUU SQL COURSE 2 BUU SQL COURSE 2 和前面那题差不多,但是注一下找到的登录成功但是显示 fault。 注一下别的看一下,在另一个数据库里找到了 flag。本文来自博客园,作者:Maplisky,转载请注明原文链接:https://www.cnblogs.com/lbh2021/p/18682313

PotPlayer 配置安装

目录一、下载1、官网链接2、微软商店 Microsoft Store二、安装1、双击安装包2、选择字体3、安装向导下一步4、接收许可协议5、选择组件及关联6、选择安装位置7、硬解选项三、设置1、关闭自动更新2、左键单双击设置3、视频下自动隐藏3.1、效果对比4、播放信息显示设置4.1、效果5…

2024年春秋杯网络安全联赛冬季赛部分wp

部分附件下载地址: https://pan.baidu.com/s/1Q6FjD5K-XLI-EuRLhxLq1Q 提取码: jay1 Misc day1-简单算术 根据提示应该是异或下载文件是一个字符串,写个代码字符串异或解密,由于需要密钥,所以先对单字节密钥进行爆破解密 爆破出flag代码如下: cipher_text = "ys~xdg/…

大夏龙雀DX-WF25(ESP32C2)蓝牙WIFI模块试用体验

模块尺寸跟引脚兼容常见的ESP8266 12-F模块,使用非常简单,vcc接3.3v,gnd接地,rx连接ch340的tx,tx连接ch340的rx即可。 如果需要通过urat下载程序,只需要把io9的引脚接地就行(下载完程序记得断开io9跟gnd的连接,否则程序无法运行)。芯片用的是ESP32C2(ESP8684),很遗…

1.20 前端连接数据库

今天完成了项目的网页前端与后端数据库的连接,已经能够将前端填写的内容添加到mysql数据库 例如页面如下:数据库内容:明天开始编写下一个功能

【vjudge训练记录】大一寒假专项训练——枚举算法

训练情况A题 给定 \((x,y)\),倒着枚举地毯的范围是否覆盖 \((x,y)\),如果覆盖直接输出,如果全部枚举完都没有则输出 -1点击查看代码 #include <bits/stdc++.h> // #define int long long #define endl \nusing namespace std;void solve(){int n; cin>>n;int x[…

Khepri C2 framework beacons记录(之前的)

1、背景 在查看进程时发现可疑隐藏进程,名称为.test(.test.93627),隐藏文件,很可疑,于是查了下进程日志发现如下:/private/tmp/.test /private/var/db/oah/4b8f81eadefb42da07e9e88fa7905df57faec82d8621008e0ae4a04d81e2169f/bb9595accf35a51de80f42e656bdb2217238af58…

(重要***)查询自己需要的SQL语句

凡是指标相关的,先清空相关干扰条件,然后点击确认,比如加载性能里的列表页面,要查慢加载次数这个指标这个时候去这个数据库 写SQL语句select* fromquery_log ql whereql.user_name = sheng.yu-n@msxf.com order byexec_time desc limit 50然后找到自己对应操作的SQL 通过结…

最强截图录屏工具ShareX v17.0.0 中文绿色版

软件介绍 ShareX 是一款功能强大的屏幕截图和屏幕录制工具,可用于创建高质量的屏幕截图、动画 GIF 和屏幕录像,并提供多种上传选项,使用户能够轻松地将它们共享到互联网上。除此之外,它还支持多种自定义功能,例如图像编辑、颜色拾取、OCR 文字识别等。软件功能快速截图:简…