[Usaco2007 Open]City Horizon 城市地平线

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.


这题困扰了苟蒻三天。。嗯。。
终于在坚持不懈理解学长的程序下大概搞懂了(呵呵。。)
首先,将坐标用线段树存储,由于坐标范围很大。。。。所以要使用动态开点(现学现卖。。。)
然后处理坐标的时候将每个区间的右端点向左移一位[Usaco2007 Open]City Horizon 城市地平线_第1张图片
嗯对,仔细想想就是为了避免这种特殊情况,你说如果中间的房子高度为1交界处应该算多少呢(貌似图画残了哈哈哈哈哈)。。
然后对于每个区间多插一个[x-1,x-1],高度为0的区间(假设建筑物两两有间隔)
计算的时候现将所有区间排序,每次找出两两相邻的区间,看右端点所在位置和右端点位置-1处高度,分类讨论之bulabulabula...

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
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;
}

你可能感兴趣的:(线段树)