著作権:帰属、紙ベースを作成するために他人を許可し、(同じライセンスで元のライセンス契約に基づいて用紙配布する必要がありますクリエイティブコモンズ)
リンク:https://ac.nowcoder.com/acm/contest/945/F
出典:牛オフネットワーク
タイトル説明
ファーマージョンは都市への旅行で彼の牛を取りました!太陽のセットとして、牛が街の地平線を見つめると長方形の建物によって形成された美しいシルエットを観察します。
全体の地平線は、N(40,000≤1≤N)建物が数直線で表されます。ビル私のシルエットは、(1≤愛<バイ≤1,000,000,000)を水平線に沿ってバイ経由地に愛をまたがると高さのHi(1≤こんにちは≤1,000,000,000)を持つベースを持っています。すべてのNの建物により形成された凝集体のシルエットの平方単位の面積を、決定します。
説明を入力します。
1行目:単一の整数:N
行2 ... N + 1:愛、Bi及びこんにちは:入力ラインI + 1は3スペースで区切られた整数で私の構築について説明し
输出描述:
、総面積、平方単位:ライン1すべてのNの建物によって形成されたシルエットの
入力サンプル
4
2 5 1
9 10 4
6 8 2
4 6 3
出力サンプル
16
说明
1 = 16 -総面積はわずか31 + 14 + 22 + 23であるように、第1の建物は、1つの平方単位の面積のための第四の建物と重なります。
問題解決のアイデア:
スコープが大きすぎるので、最初の離散データ。次いで、スクライブライン方向(ここで選択された高さ方向)の一方側、間隔L-格納離散セグメントツリーの幅。
次いで、横方向縁部は、順次各辺、領域横断、ローからハイにソート(取得セグメントツリートラバーサルの幅*高さ前縁と一方の側差)答えを得るために蓄積
/*
* Copyright (c) 2019 Ng Kimbing, HNU, All rights reserved. May not be used, modified, or copied without permission.
* @Author: Ng Kimbing, HNU.
* @LastModified:2019-06-25 T 15:07:41.265 +08:00
*/
package ACMProblems.QianDaoTi;
import java.util.Arrays;
import java.util.Comparator;
import static ACMProblems.ACMIO.*;
/*
* 链接:https://ac.nowcoder.com/acm/contest/945/F
* 来源:牛客网
*
* ## 题目描述
* Farmer John has taken his cows on a trip to the city! As the sun sets, the cows gaze at the city horizon and observe the beautiful silhouettes formed by the rectangular buildings.
* The entire horizon is represented by a number line with N (1 ≤ N ≤ 40,000) buildings. Building i's silhouette has a base that spans locations Ai through Bi along the horizon (1 ≤ Ai < Bi ≤ 1,000,000,000) and has height Hi (1 ≤ Hi ≤ 1,000,000,000). Determine the area, in square units, of the aggregate silhouette formed by all N buildings.
* ## 输入描述:
* Line 1: A single integer: N
* Lines 2..N+1: Input line i+1 describes building i with three space-separated integers: Ai, Bi, and Hi
* 输出描述:
* Line 1: The total area, in square units, of the silhouettes formed by all N buildings
* ## Input Sample
* >4
* 2 5 1
* 9 10 4
* 6 8 2
* 4 6 3
* ## Output Sample
* >16
*
* **说明**
* The first building overlaps with the fourth building for an area of 1 square unit, so the total area is just 31 + 14 + 22 + 23 - 1 = 16.
*/
public class BuildingShadow2 {
private static final int N = 40005;
static class Edge {
long left;
long right;
long height;
int upOrDown;
Edge() {}
Edge(long left, long right, long height, int upOrDown) {
this.left = left;
this.right = right;
this.height = height;
this.upOrDown = upOrDown;
}
}
/**
* [x[left], x[right+1]]
*/
static class Node {
int left;
int right;
int overlapCompletely;
long coverLength;
Node() {}
Node(int left, int right, int overlapCompletely, long coverLength) {
this.left = left;
this.right = right;
this.overlapCompletely = overlapCompletely;
this.coverLength = coverLength;
}
}
private static Edge[] edges = new Edge[N << 1];
private static Node[] nodes = new Node[N * 8];
private static long[] x = new long[2 * N];
private static void build(int i, int l, int r) {
nodes[i] = new Node(l, r, 0, 0);
if (l == r)
return;
int mid = (nodes[i].left + nodes[i].right) >> 1;
build(i << 1, l, mid);
build(i << 1 | 1, mid + 1, r);
}
private static void pushUp(int i) {
if (nodes[i].overlapCompletely != 0) {
nodes[i].coverLength = x[nodes[i].right + 1] - x[nodes[i].left];
}
/*
* remove edge
* if is leaf
*/
else if (nodes[i].left == nodes[i].right)
nodes[i].coverLength = 0;
// remove edge, if is not leaf
else
nodes[i].coverLength = nodes[i << 1].coverLength + nodes[i << 1 | 1].coverLength;
}
private static void update(int i, int targetL, int targetR, int upOrDown) {
if (nodes[i].left == targetL && nodes[i].right == targetR) {
nodes[i].overlapCompletely += upOrDown;
pushUp(i);
return;
}
int mid = (nodes[i].left + nodes[i].right) >> 1;
if (targetR <= mid)
update(i << 1, targetL, targetR, upOrDown);
else if (targetL > mid)
update(i << 1 | 1, targetL, targetR, upOrDown);
else {
update(i << 1, targetL, mid, upOrDown);
update(i << 1 | 1, mid + 1, targetR, upOrDown);
}
pushUp(i);
}
private static int lowerBound(long[] array, int size, long key) {
int first = 0, middle;
int half, len;
len = size;
while (len > 0) {
half = len >> 1;
middle = first + half;
if (array[middle] < key) {
first = middle + 1;
len = len - half - 1;
} else
len = half;
}
return first;
}
public static void main(String[] args) throws Exception {
setStream(System.in);
int total = 0;
int n = nextInt();
for (int i = 0; i < n; ++i) {
long a, b, h;
a = nextLong();
b = nextLong();
h = nextLong();
edges[total] = new Edge(a, b, 0, 1);
edges[total + 1] = new Edge(a, b, h, -1);
x[total] = a;
x[total + 1] = b;
total += 2;
}
edges[total] = new Edge();
Arrays.sort(edges, 0, total, Comparator.comparingLong(o -> o.height));
Arrays.sort(x, 0, total);
// 去重复
int k = 1;
for (int i = 1; i < total; ++i)
if (x[i] != x[i - 1])
x[k++] = x[i];
build(1, 0, k - 2);
long ans = 0;
// For each edge
for (int i = 0; i < total; ++i) {
// l, r are the index of the current edge.
int l = lowerBound(x, k, edges[i].left);
int r = lowerBound(x, k, edges[i].right) - 1;
update(1, l, r, edges[i].upOrDown);
ans += (edges[i + 1].height - edges[i].height) * nodes[1].coverLength;
}
System.out.println(ans);
}
}