【BZOJ1645】[Usaco2007 Open]City Horizon 城市地平线 离散化+线段树

时间:2023-03-09 15:45:41
【BZOJ1645】[Usaco2007 Open]City Horizon 城市地平线 离散化+线段树

【BZOJ1645】[Usaco2007 Open]City Horizon 城市地平线

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.

题解:一看就是离散化+线段树的题,可以先将h离散,再按a,b排序,用线段树维护扫描线来做,不过这样比较麻烦。

因为本题中所有的矩形底边都在同一直线上,所以我们可以把这些矩形整体看成一棵线段树,线段树的区间就是每个a,b,线段树的权值就是h,然后按h排序,从小到大一个一个加到线段树里就行了。

注意:a和b离散化后是2*40000的空间,所以线段树要开8*40000!2*4==8!!!

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lson x<<1
#define rson x<<1|1
using namespace std;
const int maxn=40010;
typedef long long ll;
struct edges
{
ll pos,org;
}s[maxn<<1];
struct house
{
ll sa,sb,sh;
}p[maxn];
int n,m;
ll ts[maxn<<3],tag[maxn<<3],ref[maxn<<1];
bool cmp1(edges a,edges b)
{
return a.pos<b.pos;
}
bool cmp2(house a,house b)
{
return a.sh<b.sh;
}
void pushdown(int l,int r,int x)
{
if(tag[x])
{
int mid=l+r>>1;
ts[lson]=(ref[mid]-ref[l])*tag[x],ts[rson]=(ref[r]-ref[mid])*tag[x];
tag[lson]=tag[rson]=tag[x];
tag[x]=0;
}
}
void pushup(int x)
{
ts[x]=ts[lson]+ts[rson];
}
void updata(int l,int r,int x,int a,int b,ll v)
{
if(a<=l&&r<=b)
{
ts[x]=(ref[r]-ref[l])*v;
tag[x]=v;
return ;
}
pushdown(l,r,x);
int mid=l+r>>1;
if(b<=mid) updata(l,mid,lson,a,b,v);
else if(a>=mid) updata(mid,r,rson,a,b,v);
else updata(l,mid,lson,a,b,v),updata(mid,r,rson,a,b,v);
pushup(x);
}
int main()
{
scanf("%d",&n);
int i;
for(i=1;i<=n;i++)
{
scanf("%lld%lld%lld",&p[i].sa,&p[i].sb,&p[i].sh);
s[i*2-1].pos=p[i].sa,s[i*2].pos=p[i].sb;
s[i*2-1].org=s[i*2].org=i;
}
sort(s+1,s+2*n+1,cmp1);
for(i=1;i<=2*n;i++)
{
if(s[i].pos>ref[m]) ref[++m]=s[i].pos;
if(s[i].pos==p[s[i].org].sa) p[s[i].org].sa=m;
else p[s[i].org].sb=m;
}
sort(p+1,p+n+1,cmp2);
for(i=1;i<=n;i++)
updata(1,m,1,p[i].sa,p[i].sb,p[i].sh);
printf("%lld",ts[1]);
return 0;
}