所谓离散化(这里讨论一维离散化),就是一个直线上的点集,我们忽略他们之间的距离大小,只考虑他们的相对位置,这就是离散化
比如点集1 5 8 3可以离散化成1 3 4 2这样子他们的相对位置不变,但是最高位点就大大缩小了,解决了线段树的空间要求
如何实行离散化: 我们可以开一个数组 a[1] = 1, a[3] = 4. a[4] = 8, a[2] = 3这样子就可以完成离散后的点对原点的映射,那么反过来呢,我们可以使用2分查找,lgn复杂度找到原点到离散后的点的映射。
解决了线段树的空间问题,这题就变得很容易了,我们要求矩形的并,而且这题所有矩形的低端都是对齐的,所以我们不用考虑低端,只需考虑高度和水平距离,这恰好符合一维线段树,每次插入一个矩形,我们就可以插入这段水平边,然后记录它的高度,最后就很方便的统计面积了。
#include <algorithm>
#include <iostream>
using namespace std;
const int N=40010;
struct tree
{
__int64 l,r;//是离散化的点的位次
__int64 high;
}t[8*N];
struct Point
{
int beg,end;
int hi;
}dia[N];
int node[2*N];
int all;
void maketree(int c,int l,int r)
{
t[c].l = l;
t[c].r = r;
t[c].high = 0;
if(l+1==r)
{
return ;
}
int mid = (l+r)>>1;
maketree(c*2,l,mid);
maketree(2*c+1,mid,r);
}
void update(int c,int l,int r,int num)
{
if(t[c].l==l && t[c].r==r)
{
t[c].high = num;
return ;
}
if(t[c].high != 0)
{
t[2*c].high = t[2*c+1].high = t[c].high;
t[c].high = 0;
}
int mid = (t[c].l + t[c].r) >> 1;
if(r<=mid)
update(2*c,l,r,num);
else if(l>=mid)
update(2*c+1,l,r,num);
else
{
update(2*c,l,mid,num);
update(2*c+1,mid,r,num);
}
}
long long findans(int c)
{
__int64 sum1,sum2;
if(t[c].high != 0 || t[c].l+1 == t[c].r)
{
return (__int64) (t[c].high * ( node[t[c].r]-node[t[c].l]) );
}
else
{
sum1 = findans(c*2);
sum2 = findans(c*2+1);
return sum1 + sum2;
}
}
int f(int num)
{
int l=1,r=all;
while(l<=r)
{
int mid = (l+r)>>1;
if(num == node[mid])
return mid;
if(num < node[mid])
r = mid - 1;
else
l = mid + 1;
}
}
int cmp(const void *a,const void *b)
{
if( (*(Point *)a).hi ==(*(Point *)b).hi)
return (*(Point *)a).beg-(*(Point *)b).beg;
else
return (*(Point *)a).hi-(*(Point *)b).hi;
}
int main()
{
int n,i;
__int64 ans=0;
int cnt = 1;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%I64d %I64d %I64d",&dia[i].beg,&dia[i].end,&dia[i].hi);
node[cnt++] = dia[i].beg;
node[cnt++] = dia[i].end;
}
sort(node+1,node+cnt);
all = 1;
for(i=2;i<cnt;i++)
{
while(i < cnt && node[i] == node[i-1]) i++;
if(i!=cnt)
node[++all] = node[i];
}
qsort(dia,n,sizeof(dia[0]),cmp);
maketree(1,1,all);
for(i=0;i<n;i++)
{
int b=f(dia[i].beg);
int e=f(dia[i].end);
//cout << b << " " << e <<endl;
update(1,b,e,dia[i].hi);
}
printf("%I64d/n",findans(1));
return 0;
}//PS:PKU数据超恶心!