1645: [Usaco2007 Open]City Horizon 城市地平线
Time Limit: 5 Sec
Memory Limit: 64 MB
Submit: 411
Solved: 196
[ Submit][ Status][ Discuss]
Description
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 A_i through B_i along the horizon (1 <= A_i < B_i <= 1,000,000,000) and has height H_i (1 <= H_i <= 1,000,000,000). Determine the area, in square units, of the aggregate silhouette formed by all N buildings.
N个矩形块,交求面积并.
Input
* Line 1: A single integer: N
* Lines 2..N+1: Input line i+1 describes building i with three space-separated integers: A_i, B_i, and H_i
Output
* Line 1: The total area, in square units, of the silhouettes formed by all N buildings
Sample Input
4
2 5 1
9 10 4
6 8 2
4 6 3
Sample Output
16
OUTPUT DETAILS:
The first building overlaps with the fourth building for an area of 1
square unit, so the total area is just 3*1 + 1*4 + 2*2 + 2*3 - 1 = 16.
这题困扰了苟蒻三天。。嗯。。
终于在坚持不懈理解学长的程序下大概搞懂了(呵呵。。)
首先,将坐标用线段树存储,由于坐标范围很大。。。。所以要使用动态开点(现学现卖。。。)
然后处理坐标的时候将每个区间的右端点向左移一位
嗯对,仔细想想就是为了避免这种特殊情况,你说如果中间的房子高度为1交界处应该算多少呢(貌似图画残了哈哈哈哈哈)。。
然后对于每个区间多插一个[x-1,x-1],高度为0的区间(假设建筑物两两有间隔)
计算的时候现将所有区间排序,每次找出两两相邻的区间,看右端点所在位置和右端点位置-1处高度,分类讨论之bulabulabula...
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<cstdlib>
#include<map>
#include<cmath>
using namespace std;
const int maxn = 2e6,INF = 2e9;
typedef long long LL;
LL t[maxn];
int lt[maxn],rt[maxn],tot = 1,n,a[100000],siz = 0,i;
int x[40500],y[40500];
void Add(int o,int L,int R,int al,int ar,LL H)
{
int mid = (L + R) >> 1;
if (al <= L && R <= ar)
{
t[o] = max(t[o],H);
return;
}
if (al <= mid)
{
if (!lt[o]) lt[o] = ++tot;
Add(lt[o],L,mid,al,ar,H);
}
if (ar > mid)
{
if (!rt[o]) rt[o] = ++tot;
Add(rt[o],mid + 1,R,al,ar,H);
}
}
LL query(int o,int L,int R,int Q)
{
int mid = (L + R) >> 1;
if (L == R) return t[o];
if (Q <= mid) return max(t[o],query(lt[o],L,mid,Q));
else return max(t[o],query(rt[o],mid + 1,R,Q));
}
int main()
{
#ifndef ONLINE_JUDGE
#ifndef YZY
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#else
freopen("yzy.txt","r",stdin);
#endif
#endif
cin >> n;
LL h;
for (i = 1; i <= n; i++)
{
scanf("%d%d%lld",&x[i],&y[i],&h);
y[i]--;
Add(1,0,INF,x[i],y[i],h);
Add(1,0,INF,x[i] - 1,x[i] - 1,0);
}
for (i = 1; i <= n; i++) a[++siz] = x[i],a[++siz] = y[i];
sort(a + 1,a + siz + 1);
LL ans = 0;
LL T = query(1,0,INF,a[1]);
ans = T;
for (i = 2; i <= siz; i++)
{
if (a[i] == a[i - 1]) continue;
LL t1 = query(1,0,INF,a[i]);
LL t2 = query(1,0,INF,a[i] - 1);
if (t1 == t2) ans += (a[i] - a[i - 1]) * t1; else
if (!t2) ans += t1; else
ans += t2 * (a[i] - a[i - 1] - 1) + t1;
}
cout << ans;
return 0;
}