Code Chef IMPO(计算几何+扫描线+积分)
题面
前置芝士
扫描线,积分求面积
题解
我怎么老是忘了积分可以求面积……
首先,这两个投影的最小的\(x\)坐标和最大的\(x\)坐标必须相等,否则肯定无解
我们考虑一种方法,枚举\(x\)坐标,并令每一个\(x\)处对应的多边形的面积最大。只有每一个\(x\)处面积都取最大,多面体的体积才能取到最大值
怎么样才能让对应的多边形面积最大呢?我们令\(h(c)\)表示\(xy\)平面上\(x=c\)处投影的长度之和,令\(g(c)\)表示\(xz\)平面上\(x=c\)处的投影长度之和。注意,因为投影不一定是个凸多边形,所以\(x=c\)处的投影不一定连续
可以发现\(h(x)\)和\(g(x)\)都是个一次函数(具体怎么发现后面会求的),分别设为\(h(x)=ax+b,g(x)=cx+d\),那么\(x\)处能取到的最大面积就是\(f(x)=h(x)\times g(x)=acx^2+(ad+bc)x+bd\),那么\([l,r]\)这一段区间的面积就是
\]
其中
\]
然后我们用扫描线来处理了,引用一下官方题解的图

我们要求那块阴影部分的面积,根据上面的讨论,我们只需要知道\([x_1,x_2]\)这段区间内每个\(x\)处阴影的长度是多少。那么就是\(AB\)上该点的\(y\)坐标减去\(AF\)上该点的\(y\)坐标加上\(EF\)减去\(CD\),这样加入加入或删除直线我们就可以\(O(1)\)维护\(abcd\)了
信心满满交上去发现全\(WA\),然后发现我们计算面积的时候不能两个定积分相减,因为精度会爆炸,得拆成以下形式
\]
然后精度就没问题了
//minamoto
#include<bits/stdc++.h>
#define R register
#define inf 0x3f3f3f3f
#define inline __inline__ __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
const int N=5e5+5;const double inv3=1.0/3,eps=1e-8;
inline int sgn(R double x){return x<-eps?-x:x;}
struct Point{int x,y;}A[N],B[N];
struct Line{
double k,b;
inline Line(){}
inline Line(R double kk,R double bb):k(kk),b(bb){}
inline Line(const Point &p,const Point &q){
k=1.0*(q.y-p.y)/(q.x-p.x),b=p.y-p.x*k;
}
inline Line op(){return Line(-k,-b);}
};
struct node{
Line L;int v;bool k;
inline bool operator <(const node &b)const{return v<b.v;}
}st[N];int top;
void init(int n,Point *a,bool k){
a[n+1]=a[1];
fp(i,1,n)if(a[i].x!=a[i+1].x){
Point p=a[i],q=a[i+1];Line L(p,q);
st[++top]={L,p.x,k};
st[++top]={L.op(),q.x,k};
}
}
int n,m;
int main(){
// freopen("testdata.in","r",stdin);
for(int T=read();T;--T){
int mxa=-inf,mna=inf,mxb=-inf,mnb=inf;top=0;
n=read();
fp(i,1,n)A[i].x=read(),A[i].y=read(),cmax(mxa,A[i].x),cmin(mna,A[i].x);
m=read();
fp(i,1,m)B[i].x=read(),B[i].y=read(),cmax(mxb,B[i].x),cmin(mnb,B[i].x);
if(mxa!=mxb||mna!=mnb){puts("-1");continue;}
init(n,A,0),init(m,B,1);
sort(st+1,st+1+top);
double l,r,res=0,k[2]={0,0},b[2]={0,0};
for(R int i=1;i<top;){
l=st[i].v;
while(i<=top&&!sgn(st[i].v-l)){
k[st[i].k]+=st[i].L.k,
b[st[i].k]+=st[i].L.b,
++i;
}
if(i>top)break;
r=st[i].v;
res+=(r-l)*(k[0]*k[1]*(l*l+l*r+r*r)*inv3+(l+r)*(b[0]*k[1]+b[1]*k[0])*0.5+b[0]*b[1]);
}
printf("%.10lf\n",res);
}
return 0;
}
Code Chef IMPO(计算几何+扫描线+积分)的更多相关文章
- Code Chef MINPOLY(计算几何+dp)
题面 传送门 题解 我们枚举这个凸多边形\(y\)坐标最小的点\(p_i\),然后对于所有\(y\)坐标大于等于它的点极角排序 我们预处理出\(s_{j,k}\)表示三角形\(p_i,p_j,p_k\ ...
- Code Chef DARTSEGM(计算几何+凸包)
题面 传送门 题解 好眼熟丫-- 一月月赛最后一题--,代码都不用改-- //minamoto #include<bits/stdc++.h> #define R register #de ...
- CodeForces 1216C(假的计算几何+扫描线)
传送门 •题意 给你三个矩形,依次编号为 1,2,3: 判断 矩形1 是否被 矩形2 和 矩形3 完全覆盖: 如果没有完全覆盖,输出 "YES",反之,输出 "NO&qu ...
- BZOJ 1845: [Cqoi2005] 三角形面积并 [计算几何 扫描线]
1845: [Cqoi2005] 三角形面积并 Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 1151 Solved: 313[Submit][Stat ...
- BZOJ2178 圆的面积并 计算几何 辛普森积分
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ2178.html 题目传送门 - BZOJ2178 题意 给出 $n(n\leq 1000)$ 个圆,求 ...
- 【Code Chef】April Challenge 2019
Subtree Removal 很显然不可能选择砍掉一对有祖先关系的子树.令$f_i$表示$i$子树的答案,如果$i$不被砍,那就是$a_i + \sum\limits_j f_j$:如果$i$被砍, ...
- Code Chef April Cook-Off 2019题解
传送门 \(PEWDSVTS\) 我哪根筋不对了要把所有可行的拿出来\(sort\)一下--还有忘开\(long\ long\)真的好难受-- int main(){ // freopen(" ...
- Code Chef December Challenge 2018题解
传送门 \(MAXEP\) 二分,不过二分的时候要注意把\(mid\)设成\(\left\lfloor{9l+r\over 10}\right\rfloor\),这样往右的次数不会超过\(6\)次 / ...
- Code Chef JUMP(递推+树状数组+李超线段树)
\(JUMP\) 很容易写出转移柿子 \[f_i=\min_{p_j<p_i}\{(h_i-h_j)^2+f_j\}+w_i\] 把\(\min\)里面的东西展开一下 \[f_j=\min_{p ...
随机推荐
- js字符转换为数字
转换函数.强制类型转换.利用js变量弱类型转换. 1. 转换函数: js提供了parseInt()和parseFloat()两个转换函数.前者把值转换成整数,后者把值转换成浮点数.只有对String类 ...
- gzip是一种数据格式,deflate是一种压缩算法
gzip是一种数据格式,默认且目前仅使用deflate算法压缩data部分:deflate是一种压缩算法,是huffman编码的一种加强. deflate与gzip解压的代码几乎相同,可以合成一块代码 ...
- 读取指定路径的Properties文件
1.读取项目内的properties文件,项目内的properties文件一般都放在resource文件夹下面, 通过getClassLoader().getResourceAsStream()来获取 ...
- Spring分配置文件开发
---------------------siwuxie095 Spring 分配置文件开发 Spring 分配置文件开 ...
- errorlevel 续1
-------siwuxie095 常用 errorlevel 返回值: backup 0 备份成功 1 未找到备份文件 2 文件共享冲突阻止备份完成 3 用户用 ct ...
- MD5加密算法原理及其应用
MD5是一个安全的散列算法,输入两个不同的明文不会得到相同的输出值,根据输出值,不能得到原始的明文,即其过程不可逆:所以要解密MD5没有现成的算法,只能用穷举法,把可能出现的明文,用MD5算法散列之后 ...
- MongoDB中使用的SCRAM-SHA1认证机制
摘要: 介绍 SCRAM是密码学中的一种认证机制,全称Salted Challenge Response Authentication Mechanism. SCRAM适用于使用基于『用户名:密码』这 ...
- ios 单个ViewController屏幕旋转
如果需要旋转的ViewController 使用了UINavigationController,对UINavigationController进行如下扩展 @implementation UINavi ...
- [Training Video - 4] [Groovy] String Functions
def x="I like to read books before bed" def temp = x.split(" ") log.info "S ...
- sqlserver 2017 linux还原windows备份时的路径问题解决
windows的备份由于路径问题,在Linux上会报错 File 'YourDB_Product' cannot be restored to 'Z:\Microsoft SQL Server\MSS ...