题目2 : 三角形面积和
时间限制:
10000ms
单点时限:
1000ms
内存限制:
256MB
-
3 7 3 4 4 11 5
样例输出
-
42.00
描述
如下图所示,在X轴上方一共有N个等腰直角三角形。这些三角形的斜边与X轴重合,斜边的对顶点坐标是(Xi, Yi)。
(11,5) (4,4) /\ /\(7,3) \ / \/\/ \ / /\/\ \ / / /\ \ \ ------------------------->
你能求出这些三角形覆盖的面积之和吗? (重叠部分只算一次)
输入
第一行包含一个整数N。
以下N行每行包含两个整数(Xi, Yi),代表第i个三角形顶点的坐标。
对于30%的数据,1 ≤ N ≤ 100, 0 ≤ Xi, Yi ≤ 100
对于100%的数据,1 ≤ N ≤ 100000,0 ≤ Xi, Yi ≤ 100000
输出
覆盖的面积,保留2位小数。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <bits/stdc++.h>
using namespace std;
struct Triangle{
int top,l,r;
Triangle(){}
Triangle(int x,int y){
top=y;
l=x-y;
r=x+y;
}
friend bool operator<(const Triangle &a,const Triangle &b){
if(a.r==b.r)return a.top<b.top;
return a.r<b.r;
}
};
double calculate(Triangle a,Triangle b){
double r1=a.r;
double l2=b.l;
double top2=b.top;
return top2*top2-(r1-l2)*(r1-l2)*0.25;
//return ((r1-l2)*top2-(r1-l2)*(r1-l2)/2.0+2*top2*top2-top2*(r1-l2))/2.0;
//return ((r1-l2)/sqrt(2)+sqrt(2)*top2)*(sqrt(2)*top2-(r1-l2)/sqrt(2))/2.0;
}
Triangle A[100009];
Triangle B[100009];//a list
/*
2
0 100000
100000 100000
*/
int main(){
int N;
cin>>N;
for(int i=0;i<N;i++){
int x,y;
cin>>x>>y;
A[i]=Triangle(x,y);
}
sort(A,A+N);
B[0]=A[0];
int num=1;
for(int i=1;i<N;i++){
while(num>0&&((B[num-1].l>=A[i].l)||(B[num-1].r==A[i].r)))num--;//
B[num++]=A[i];
}
double S=(double)B[0].top*(double)B[0].top;
for(int i=1;i<num;i++){
if(B[i].l>B[i-1].r){
S+=(double)B[i].top*(double)B[i].top;
continue;
}
S+=calculate(B[i-1],B[i]);
}
printf("%.2lf\n",S);
return 0;
}
//
// _oo0oo_
// o8888888o
// 88" . "88
// (| -_- |)
// 0\ = /0
// ___/`---'\___
// .' \\| |// '.
// / \\||| : |||// \
// / _||||| -:- |||||- \
// | | \\\ - /// | |
// | \_| ''\---/'' |_/ |
// \ .-\__ '-' ___/-. /
// ___'. .' /--.--\ `. .'___
// ."" '< `.___\_<|>_/___.' >' "".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `_. \_ __\ /__ _/ .-` / /
// =====`-.____`.___ \_____/___.-`___.-'=====
// `=---='
//
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// 佛祖保佑 永无BUG
//
//
//
思路:先按照三角形的右下角的端点坐标排序,然后去掉包含的情况,从左到右加面积就行了
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <bits/stdc++.h>
using namespace std;
struct Triangle{
int top,l,r;
Triangle(){}
Triangle(int x,int y){
top=y;
l=x-y;
r=x+y;
}
friend bool operator<(const Triangle &a,const Triangle &b){
if(a.r==b.r)return a.top<b.top;
return a.r<b.r;
}
};
double calculate(Triangle a,Triangle b){
double r1=a.r;
double l2=b.l;
double top2=b.top;
return top2*top2-(r1-l2)*(r1-l2)*0.25;
//return ((r1-l2)*top2-(r1-l2)*(r1-l2)/2.0+2*top2*top2-top2*(r1-l2))/2.0;
//return ((r1-l2)/sqrt(2)+sqrt(2)*top2)*(sqrt(2)*top2-(r1-l2)/sqrt(2))/2.0;
}
Triangle A[100009];
Triangle B[100009];//a list
/*
2
0 100000
100000 100000
*/
int main(){
int N;
cin>>N;
for(int i=0;i<N;i++){
int x,y;
cin>>x>>y;
A[i]=Triangle(x,y);
}
sort(A,A+N);
B[0]=A[0];
int num=1;
for(int i=1;i<N;i++){
while(num>0&&((B[num-1].l>=A[i].l)||(B[num-1].r==A[i].r)))num--;//
B[num++]=A[i];
}
double S=(double)B[0].top*(double)B[0].top;
for(int i=1;i<num;i++){
if(B[i].l>B[i-1].r){
S+=(double)B[i].top*(double)B[i].top;
continue;
}
S+=calculate(B[i-1],B[i]);
}
printf("%.2lf\n",S);
return 0;
}
//
// _oo0oo_
// o8888888o
// 88" . "88
// (| -_- |)
// 0\ = /0
// ___/`---'\___
// .' \\| |// '.
// / \\||| : |||// \
// / _||||| -:- |||||- \
// | | \\\ - /// | |
// | \_| ''\---/'' |_/ |
// \ .-\__ '-' ___/-. /
// ___'. .' /--.--\ `. .'___
// ."" '< `.___\_<|>_/___.' >' "".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `_. \_ __\ /__ _/ .-` / /
// =====`-.____`.___ \_____/___.-`___.-'=====
// `=---='
//
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// 佛祖保佑 永无BUG
//
//
//