#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
using namespace std;
class Dread{
private:
bool isdigit(char ch) { return ch >= '0' && ch <= '9'; }
bool isalpha(char ch) { return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); }
void Getchar(int &tmp){
char ch; tmp = 0; bool b = true;
while (ch = getchar()){
if (ch == '-') b = false;
if (isdigit(ch)) break;
}
for (; isdigit(ch); ch = getchar()) tmp = tmp * 10 + ch - '0';
if (!b) tmp = -tmp;
}
void Getchar(char &tmp){
while (tmp = getchar()) if (isalpha(tmp)) break;
}
public:
int Int(){ int x; Getchar(x); return x; }
char Ch(){ char x; Getchar(x); return x; }
}Read;
const int maxn = 101111;
const int maxm = 1010000;
struct zy{
int x, y, d, l, r;
bool operator < (const zy a) const { return y < a.y; }
bool operator > (const zy b) const { return l <= b.l && b.r <= r; }
}a[maxn];
int q[maxn];
int sum[maxm], n;
int next[maxn], last[maxn];
bool b[maxn];
int maxh = 0;
void init(){
n = Read.Int();
for (int i = 1; i <= n; i ++){
a[i].x = Read.Int(), a[i].y = Read.Int(), a[i].d = Read.Int();
a[i].l = a[i].x, a[i].r = a[i].x + a[i].d;
next[i] = i + 1, last[i] = i - 1;
maxh = max(maxh, a[i].d + a[i].y);
}
}
int head;
void Delete(int j){
if (j == head) head = next[j];
last[next[j]] = last[j];
next[last[j]] = next[j];
b[j] = false;
}
void work(){
sort(a + 1, a + n + 1);
memset(b, 1, sizeof(b));
double len = 0;
head = 1;
for (int i = 1; i <= n && a[i].y == a[1].y; i ++)
for (int j = a[i].l; j < a[i].r; j ++){
if (!sum[j]) len ++;
sum[j] ++;
}
double ans = 0;
for (int i = a[1].y + 1; i <= maxh; i ++){
double lastlen = len;
int ww = 0;
for (int j = head; a[j].y < i && j <= n; j = next[j]){
a[j].r --;
if (a[j].r < a[j].x) Delete(j);
else {
sum[a[j].r] --;
if (!sum[a[j].r]) len --;
q[++ww] = j;
}
}
ans += (lastlen + len) * 1.0 / 2.0;
for (int j = head; a[j].y <= i && j <= n; j = next[j])
if (a[j].y == i){
int k;
for (k = 1; k <= ww; k ++){
if (!b[q[k]]) continue;
if (a[q[k]] > a[j]){
Delete(j);
break;
}
if (a[j] > a[q[k]]){
Delete(q[k]);
for (int kk = a[q[k]].l; kk < a[q[k]].r; kk ++){
sum[kk] --;
if (!sum[kk]) len --;
}
}
}
if (k <= ww) continue;
for (int kk = a[j].l; kk < a[j].r; kk ++){
if (!sum[kk]) len ++;
sum[kk] ++;
}
}
}
printf("%.1lf\n", ans);
}
int main(){
init();
work();
return 0;
}
2731: [HNOI2012]三角形覆盖问题
Time Limit: 20 Sec Memory Limit: 128 MB
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
using namespace std;
class Dread{
private:
bool isdigit(char ch) { return ch >= '0' && ch <= '9'; }
bool isalpha(char ch) { return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); }
void Getchar(int &tmp){
char ch; tmp = 0; bool b = true;
while (ch = getchar()){
if (ch == '-') b = false;
if (isdigit(ch)) break;
}
for (; isdigit(ch); ch = getchar()) tmp = tmp * 10 + ch - '0';
if (!b) tmp = -tmp;
}
void Getchar(char &tmp){
while (tmp = getchar()) if (isalpha(tmp)) break;
}
public:
int Int(){ int x; Getchar(x); return x; }
char Ch(){ char x; Getchar(x); return x; }
}Read;
const int maxn = 101111;
const int maxm = 1010000;
struct zy{
int x, y, d, l, r;
bool operator < (const zy a) const { return y < a.y; }
bool operator > (const zy b) const { return l <= b.l && b.r <= r; }
}a[maxn];
int q[maxn];
int sum[maxm], n;
int next[maxn], last[maxn];
bool b[maxn];
int maxh = 0;
void init(){
n = Read.Int();
for (int i = 1; i <= n; i ++){
a[i].x = Read.Int(), a[i].y = Read.Int(), a[i].d = Read.Int();
a[i].l = a[i].x, a[i].r = a[i].x + a[i].d;
next[i] = i + 1, last[i] = i - 1;
maxh = max(maxh, a[i].d + a[i].y);
}
}
int head;
void Delete(int j){
if (j == head) head = next[j];
last[next[j]] = last[j];
next[last[j]] = next[j];
b[j] = false;
}
void work(){
sort(a + 1, a + n + 1);
memset(b, 1, sizeof(b));
double len = 0;
head = 1;
for (int i = 1; i <= n && a[i].y == a[1].y; i ++)
for (int j = a[i].l; j < a[i].r; j ++){
if (!sum[j]) len ++;
sum[j] ++;
}
double ans = 0;
for (int i = a[1].y + 1; i <= maxh; i ++){
double lastlen = len;
int ww = 0;
for (int j = head; a[j].y < i && j <= n; j = next[j]){
a[j].r --;
if (a[j].r < a[j].x) Delete(j);
else {
sum[a[j].r] --;
if (!sum[a[j].r]) len --;
q[++ww] = j;
}
}
ans += (lastlen + len) * 1.0 / 2.0;
for (int j = head; a[j].y <= i && j <= n; j = next[j])
if (a[j].y == i){
int k;
for (k = 1; k <= ww; k ++){
if (!b[q[k]]) continue;
if (a[q[k]] > a[j]){
Delete(j);
break;
}
if (a[j] > a[q[k]]){
Delete(q[k]);
for (int kk = a[q[k]].l; kk < a[q[k]].r; kk ++){
sum[kk] --;
if (!sum[kk]) len --;
}
}
}
if (k <= ww) continue;
for (int kk = a[j].l; kk < a[j].r; kk ++){
if (!sum[kk]) len ++;
sum[kk] ++;
}
}
}
printf("%.1lf\n", ans);
}
int main(){
init();
work();
return 0;
}
Submit: 172 Solved: 95
[ Submit][ Status]
Description
二维平面中,给定
N个等腰直角三角形(每个三角形的两条直角边分别
平行于坐标轴,斜边从左上到右下)。我们用三个非负整数(
x,
y,
d)来描
述这样一个三角形,三角形三个顶点的坐标
分别为(
x,
y), (
x +
d,
y)和(
x,
y +
d)。要求计算这
N个三角形所覆盖的总面
积。例如,下图有 3 个三角形,覆盖的总面积为 11.0。
Input
输入文件第一行为一个正整数N,表示三角形的个数。接下来的N
行每行有用空格隔开的三个非负整数, x,y , d,描述一个三角
形的顶点坐标,分别为
( x, y), (x+ d, y), ( x,y+d),
其中 x, y,d 满足0≤ x, y, d≤1000000。
对于50%的数据,1≤ N≤500;
100%的数据,1≤N≤10000。
Output
仅包含一行,为一个实数 S ,表示所有三角形所覆盖的总面积,输出恰
好保留一位小数。输入数据保证 S≤2^31。
Sample Input
3 .
1 1 4
2 0 2
3 2 2
1 1 4
2 0 2
3 2 2
Sample Output
11.0
HINT
Source
从最低点弄根扫描线,一直到最高点,每次扫描线++
两根扫描之间的面积,就是下面那根扫描线被覆盖的长度+上面那根扫描线被非底边覆盖的长度,然后除以2。
然后最坏是100000 * 1000000