首先,看到这题就感觉亮瞎,好像没有任何突破口,因为以前做过一个矩阵求并的问题,那个题目还是比较难的,但是这道题目和hdu1225所不同的地方在于,他的所有矩阵y1坐标都是0,也就是说建筑物都是落地的,不存在悬空的情况。然后我们分析他和poster这一题非常相似,但是问题在于Poster可以覆盖,而其却不存在覆盖的情况。这样是不是就不能解决了呢?当然不是。我们可以把建筑物的高度从低到高排序,然后从低向高做,这样高的建筑物就相当于覆盖了较低的建筑物。
所以加一个离散化和sort就可以解决这个问题了。
不过这题在Poj上的时候,我弄了很多遍才过。不过数据是相当恶心,n<=7000000,而且这里读入的数据并不是<=10^9而是可能超过Int,只能用%lld 不能用%i64d,实在是太恶心了,而且这题如果换成Longlong还是专门卡Map的,想偷工减料用hash都不行,必须手工写二分哈希表。
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<algorithm>
#include<map>
#define LL long long
using namespace std;
const int MAX_N = 40001;
const int root = 1;
const int other = -1;
struct node
{
LL s,e;
LL high;
};
struct node p[MAX_N*10];
LL wide[MAX_N*10];
LL dote[MAX_N*10];
struct Treenode
{
int L,R;
int Lid,Rid;
LL highest;
};
struct Treenode T[MAX_N*10];
int N;
int M;
int Q;
//map<LL,int> hash;
int times ;
struct Treenode Tn(int l,int r,int Lid,int Rid,LL highest)
{
struct Treenode tmp;
tmp.L=l;
tmp.R=r;
tmp.Lid=Lid;
tmp.Rid=Rid;
tmp.highest=highest;
return tmp;
}
void Build(int l,int r)
{
if (l>=r) {T[++times]=Tn(l,r,other,other,0);return;}
int now = ++times;
int mid = (l+r)/2;
int lid= times+1;
Build(l,mid);
int rid= times+1;
Build(mid+1,r);
T[now]=Tn(l,r,lid,rid,0);
}
bool cmp(struct node a,struct node b)
{
return a.high<=b.high;
}
void init()
{
int i;
int last;
scanf("%d",&N);
for (i=1;i<=N;i++)
scanf("%lld %lld %lld",&p[i].s,&p[i].e,&p[i].high);
for (i=1;i<=N;i++)
wide[i]=p[i].s,wide[i+N]=p[i].e;
sort(wide+1,wide+N*2+1);
last=wide[1];
M=2*N;
for (i=2;i<=2*N;i++)
{
if (wide[i]-last>1)
wide[++M]=last+1;
last=wide[i];
}
sort(wide+1,wide+M+1);
Q=0;
last=-1;
for (i=1;i<=M;i++)
if (last!=wide[i])
{
last=wide[i];
++Q;
//hash[last]=Q;
dote[Q]=last;
}
++Q;
//hash[last+1]=Q;
dote[Q]=last;
Build(1,Q);
sort(p+1,p+N+1,cmp);
}
void down_tag(int t)
{
if (T[t].highest!=other)
{
int lid=T[t].Lid;
int rid=T[t].Rid;
T[lid].highest=T[t].highest;
T[rid].highest=T[t].highest;
T[t].highest = 0;
}
}
void change(int t,int s,int e,LL color)
{
int l=T[t].L;
int r=T[t].R;
int mid=(l+r)/2;
int lid=T[t].Lid;
int rid=T[t].Rid;
if (s<=l&&e>=r) {T[t].highest=color;return ;}
down_tag(t);
T[t].highest=-1;
if (s<=mid) change(lid,s,e,color);
if (e>mid) change(rid,s,e,color);
}
int hash(LL v)
{
int lb = 1;
int rb = Q;
while (lb<rb)
{
int mid=(lb+rb)/2;
if (dote[mid]==v) return mid;
if (dote[mid]>v) rb=mid-1;
else lb=mid+1;
}
return lb;
}
void work()
{
int i;
for (i=1;i<=N;i++)
change(root,hash(p[i].s),hash(p[i].e)-1,p[i].high);
}
LL query(int t,int s,int e)
{
int l=T[t].L;
int r=T[t].R;
int mid=(l+r)/2;
int lid=T[t].Lid;
int rid=T[t].Rid;
if (T[t].highest!=-1) return T[t].highest*(dote[r+1]-dote[l]);
down_tag(t);
T[t].highest=-1;
if (e<=mid||s>mid)
return (s<=mid?query(lid,s,e):0)+(e>mid?query(rid,s,e):0);
else
return query(lid,s,mid)+query(rid,mid+1,e);
}
void put()
{
printf("%lld\n",query(root,1,Q));
}
int main()
{
freopen("horizon.in","r",stdin);
freopen("horizon.out","w",stdout);
init();
work();
put();
return 0;
}