1845: [Cqoi2005] 三角形面积并

Time Limit: 3 Sec  Memory Limit: 64 MB
Submit: 1664  Solved: 443
[Submit][Status][Discuss]

Description

给出n个三角形,求它们并的面积。

Input

第一行为n(N < = 100), 即三角形的个数
以下n行,每行6个整数x1, y1, x2, y2, x3, y3,代表三角形的顶点坐标。坐标均为不超过10 ^ 6的实数,输入数据保留1位小数

Output

输出并的面积u, 保留两位小数

Sample Input

2

0.0 0.0 2.0 0.0 1.0 1.0

1.0 0.0 3.0 0.0 2.0 1.0


Sample Output

1.75

HINT

Source

[Submit][Status][Discuss]

HOME
Back

Claris的题解

求出所有交点后从左往右扫描线,用每段的中位线去截所有三角形,算出长度并后乘以该段长度即可,时间复杂度\(O(n^3\log n)\)。

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;rg char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') w=-1;ch=getchar();}
while(isdigit(ch)) data=data*10+ch-'0',ch=getchar();
return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll;
using namespace std; co double eps=1e-9,INF=1e6;
il int sig(double x) {return abs(x)<eps?0:(x>0?1:-1);}
struct P{double x,y;};
il bool cmp(co P&u,co P&v) {return u.x<v.x;}
il P operator+(co P&u,co P&v) {return (P){u.x+v.x,u.y+v.y};}
il P operator-(co P&u,co P&v) {return (P){u.x-v.x,u.y-v.y};}
il P operator*(co P&u,double k) {return (P){u.x*k,u.y*k};}
il double cross(co P&u,co P&v) {return u.x*v.y-u.y*v.x;}
il bool has_intersection(co P&a,co P&b,co P&p,co P&q){
return sig(cross(b-a,p-a))*sig(cross(b-a,q-a))<0&&
sig(cross(q-p,a-p))*sig(cross(q-p,b-p))<0;
}
il P line_intersection(co P&a,co P&b,co P&p,co P&q){
return a+(b-a)*(cross(p-a,q-p)/cross(b-a,q-p));
} co int N=300;
int n,m;
P tri[N][4],seg[N];
double px[N*N],ans;
double cal(double x){
P D=(P){x,-INF},U=(P){x,INF};
int m=0;
for(int i=0,k=0;i<n;++i,k=0){
double y[2];
for(int j=0;j<3;++j)if(has_intersection(tri[i][j],tri[i][j+1],D,U))
y[k++]=line_intersection(tri[i][j],tri[i][j+1],D,U).y;
if(k) seg[m++]=(P){min(y[0],y[1]),max(y[0],y[1])};
}
if(m>1) sort(seg,seg+m,cmp);
double l=-INF,r=-INF,t=0;
for(int i=0;i<m;++i){
if(sig(seg[i].x-r)>0) t+=r-l,l=seg[i].x;
r=max(r,seg[i].y);
}
return t+r-l;
}
int main(){
// freopen(".in","r",stdin),freopen(".out","w",stdout);
read(n);
for(int i=0;i<n;++i){
for(int j=0;j<3;++j)
scanf("%lf%lf",&tri[i][j].x,&tri[i][j].y),px[m++]=tri[i][j].x;
tri[i][3]=tri[i][0];
}
for(int i=0;i<n;++i)for(int j=0;j<i;++j)
for(int k=0;k<3;++k)for(int l=0;l<3;++l)
if(has_intersection(tri[i][k],tri[i][k+1],tri[j][l],tri[j][l+1]))
px[m++]=line_intersection(tri[i][k],tri[i][k+1],tri[j][l],tri[j][l+1]).x;
sort(px,px+m);
for(int i=1;i<m;++i)if(sig(px[i]-px[i-1]))
ans+=(px[i]-px[i-1])*cal((px[i]+px[i-1])/2);
return printf("%.2lf\n",ans-eps),0;
}

Picture

Language:Default
Picture
Time Limit: 2000MS Memory Limit: 10000K
Total Submissions: 14427 Accepted: 7542

Description

A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical or horizontal. Each rectangle can be partially or totally covered by the others. The length of the boundary of the union of all rectangles is called the perimeter.



Write a program to calculate the perimeter. An example with 7 rectangles is shown in Figure 1.



The corresponding boundary is the whole set of line segments drawn in Figure 2.



The vertices of all rectangles have integer coordinates.

Input

Your program is to read from standard input. The first line contains the number of rectangles pasted on the wall. In each of the subsequent lines, one can find the integer coordinates of the lower left vertex and the upper right vertex of each rectangle. The values of those coordinates are given as ordered pairs consisting of an x-coordinate followed by a y-coordinate.



0 <= number of rectangles < 5000

All coordinates are in the range [-10000,10000] and any existing rectangle has a positive area.

Output

Your program is to write to standard output. The output must contain a single line with a non-negative integer which corresponds to the perimeter for the input rectangles.

Sample Input

7
-15 0 5 10
-5 8 20 25
15 -4 24 14
0 -6 16 4
2 15 10 22
30 10 36 20
34 0 40 16

Sample Output

228

Source

给出多个矩形坐标,求所有矩形的组合体的周长

A_Mango的题解

这道题的突破口是线扫描,假想一条垂直于y轴的线从下往上扫描,以矩形x轴方向的边为事件,这样只要知道当前发生事件时矩形的覆盖x轴的长度(为了计算x轴方向的边),以及由几块孤立的区域组成(为了计算y轴方向的边),但是问题就是如何在每次更新事件时更新这两个属性

这就到了线段树出场,因为如果要维护这2个属性,必须要在矩形下边的边时加入它,在上边时把它删除,能快速做到对一个线段快速修改就是线段树了,而且对于维护一个区域内的线段的总长度,以及孤立的线段数量,它也不难实现,但这时候问题来了,坐标的范围是-10000~10000,正常用这个坐标来更新线段树的话速度可能不够。所以最好的办法就是先对矩形边的x坐标离散化(不过本题中如果数据不太变态,不离散化估计也能过)

线段树的维护:这也是一个难点,越用这东西越觉得它有很多东西值得钻研。本题中要维护的2个线段树属性

  1. 覆盖的总线段长

    因为对同个区域插入多次,他的总长度还是不变,对一个区域删除的次数要等于他插入的次数才能把区域中的长度减少,所以要在每个节点加上覆盖次数cover
  2. 孤立线段的数量

    因为要判断2个子区域是否相连,加上bl,br记录当前节点左右边界是否被覆盖

时间复杂度\(O(n \log n)\)

#include<iostream>
#include<algorithm>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;rg char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') w=-1;ch=getchar();}
while(isdigit(ch)) data=data*10+ch-'0',ch=getchar();
return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll;
using namespace std; co int N=2e4+1,INF=0x3f3f3f3f;
int n,Max=-INF,Min=INF,tot,ans,pre;
struct P{
int l,r,h,k;
il bool operator<(co P&p)co {return h!=p.h?h<p.h:k>p.k;}
}a[N];
struct T{
int sum,num,len;
bool l,r;
}t[N*4];
il void add(int l,int r,int h,int k){
a[++tot].l=l,a[tot].r=r,a[tot].h=h,a[tot].k=k;
}
#define lc (p<<1)
#define rc (p<<1|1)
il void work(int p,int l,int r){
if(t[p].sum) t[p].num=t[p].l=t[p].r=1,t[p].len=r-l+1;
else if(l==r) t[p].len=t[p].num=t[p].l=t[p].r=0;
else{
t[p].len=t[lc].len+t[rc].len;
t[p].num=t[lc].num+t[rc].num;
if(t[lc].r&&t[rc].l) --t[p].num;
t[p].l=t[lc].l,t[p].r=t[rc].r;
}
}
void change(int p,int l,int r,int L,int R,int k){
if(L<=l&&r<=R) return t[p].sum+=k,work(p,l,r);
int mid=l+r>>1;
if(L<=mid) change(lc,l,mid,L,R,k);
if(R>mid) change(rc,mid+1,r,L,R,k);
work(p,l,r);
}
int main(){
// freopen(".in","r",stdin),freopen(".out","w",stdout);
read(n);
for(int i=1,x1,y1,x2,y2;i<=n;++i){
read(x1),read(y1),read(x2),read(y2);
Max=max(Max,max(x1,x2)),Min=min(Min,min(x1,x2));
add(x1,x2,y1,1),add(x1,x2,y2,-1);
}
if(Min<=0){
for(int i=1;i<=tot;++i) a[i].l+=1-Min,a[i].r+=1-Min;
Max-=Min; // len-1
}
sort(a+1,a+tot+1);
for(int i=1;i<=tot;++i){
change(1,1,Max,a[i].l,a[i].r-1,a[i].k);
while(a[i].h==a[i+1].h&&a[i].k==a[i+1].k)
++i,change(1,1,Max,a[i].l,a[i].r-1,a[i].k);
ans+=abs(t[1].len-pre),pre=t[1].len;
ans+=t[1].num*(a[i+1].h-a[i].h)*2;
}
printf("%d\n",ans);
return 0;
}

CQOI2005 三角形面积并 和 POJ1177 Picture的更多相关文章

  1. bzoj 1845: [Cqoi2005] 三角形面积并 扫描线

    1845: [Cqoi2005] 三角形面积并 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 848  Solved: 206[Submit][Statu ...

  2. BZOJ 1845: [Cqoi2005] 三角形面积并 [计算几何 扫描线]

    1845: [Cqoi2005] 三角形面积并 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 1151  Solved: 313[Submit][Stat ...

  3. [CQOI2005]三角形面积并

    [CQOI2005]三角形面积并 题目大意: 求\(n(n\le100)\)个三角形的面积并. 思路: 自适应辛普森法,玄学卡精度可过. 源代码: #include<cmath> #inc ...

  4. 【BZOJ1845】[Cqoi2005] 三角形面积并 几何+扫描线

    [BZOJ1845][Cqoi2005] 三角形面积并 Description 给出n个三角形,求它们并的面积. Input 第一行为n(N < = 100), 即三角形的个数 以下n行,每行6 ...

  5. BZOJ1845 [Cqoi2005] 三角形面积并 扫描线 计算几何

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1845 题意概括 给出n个三角形,求其面积并. 题解 有一个很经典的扫描线题目:矩形面积并.那个比较 ...

  6. BZOJ1845 : [Cqoi2005] 三角形面积并

    求出所有交点后从左往右扫描线,用每段的中位线去截所有三角形,算出长度并后乘以该段长度即可,时间复杂度$O(n^3\log n)$. #include<cstdio> #include< ...

  7. BZOJ 1845: [Cqoi2005] 三角形面积并 (辛普森积分)

    大力辛普森积分 精度什么的搞了我好久- 学到了Simpson的一个trick 深度开11,eps开1e-4.跑的比有些扫描线还快- CODE #include <bits/stdc++.h> ...

  8. UVa 11437:Triangle Fun(计算几何综合应用,求直线交点,向量运算,求三角形面积)

    Problem ATriangle Fun Input: Standard Input Output: Standard Output In the picture below you can see ...

  9. [POJ1177]Picture

    [POJ1177]Picture 试题描述 A number of rectangular posters, photographs and other pictures of the same sh ...

随机推荐

  1. zookeeper的java api操作

    zookeeper的java api操作 创建会话: Zookeeper(String connectString,int sessionTimeout,Watcher watcher) Zookee ...

  2. unix 命令

    ubuntu  命令窗口的打开 打开命令行窗口: Ctrl+Alt+T 在打开的命令行窗口中打开一个新的Tab: Ctrl+Shift+T 在同一窗口的Tab间切换: Ctrl+Page Up 或者 ...

  3. uwsgi03----直接部署

    1.http 和 http-socket的使用上有一些区别: http: 自己会产生一个http进程(可以认为与nginx同一层)负责路由http请求给worker, http进程和worker之间使 ...

  4. C++打印杨辉三角形

    #include <iostream> #include <iomanip> #include <Windows.h> using namespace std; # ...

  5. Kubernetes 学习笔记(二):本地部署一个 kubernetes 集群

    前言 前面用到过的 minikube 只是一个单节点的 k8s 集群,这对于学习而言是不够的.我们需要有一个多节点集群,才能用到各种调度/监控功能.而且单节点只能是一个加引号的"集群&quo ...

  6. Angular Material 学习笔记 Chips

    依据 material guidelines, chips 可以用来做 filter https://material.io/design/components/chips.html#filter-c ...

  7. php json_encode() 中文保留

    这几天遇到了一个问题 给java传json的时候  没有处理中文  那边拿数据的时候说不是中文的  需要转一下 方法: 实际应用中,当有中文字符时,当直接使用json_encode() 函数会使汉字不 ...

  8. .Net DLL类库引用时没有注释信息

    自己编写的类库提供给别人引用时,别人获取不到DLL内部的方法.变量的注释信息,无法了解内部情况和使用方法. 原因:没有随DLL类库一同输出注释文档 解决方案: 在VS界面中选中提供给别人的类库项目 在 ...

  9. interface Part3(实现:显示和隐式)

    1. 接口的实现实际上和类之间的继承是一样的,也是重写了接口中的方法,让其有了具体的实现内容. 2. 但需要注意的是,在类中实现一个接口时必须将接口中的所有成员都实现,否则该类必须声明为抽象类,并将接 ...

  10. 【转载】IIS网站如何同时解析带www和不带www的域名

    针对公网上线的网站系统,很多网站的域名会同时含有带www和不带www的域名解析记录,如果需要同时解析带www和不带www的域名信息,则需要在相应的域名解析平台(如阿里云域名解析平台.腾讯云域名解析平台 ...