http://poj.org/problem?id=3277
poj 3277 city horizon
注意数组大小为离散出点的四倍………………
#include<iostream>
#include<cstdio>
#include<queue>
#include <algorithm>
#include <cmath>
using namespace std;
struct node1{
int p, num, id ; //p 原本坐标 id 离散坐标 num 原始编号
}leaf[80010]; //离散出为8000点,而非4000
struct node{
int lef, rig, mid, hei;
}tree[320010]; // 数组大小为离散点数3~4倍
int n, hush[80010], height[40010], mm;
bool cmp1( node1 x, node1 y){
if( x.p== y.p) return x.num< y.num;
return x.p< y.p;
}
bool cmp2( node1 x, node1 y){
return x.num< y.num;
}
int max( int x, int y){
return x>y?x:y;
}
void init(){
int i, j, k, l, r, h, temp;
for( i=0; i<n; i++){
scanf("%d%d%d", &l, &r, &h);
leaf[2*i].p= l;
leaf[2*i+ 1].p= r;
leaf[2*i].num=2*i;
leaf[2*i+ 1].num= 2*i+1;
height[i]= h;
}
sort( leaf, leaf+ 2*n, cmp1);
hush[0]= leaf[0].p, leaf[0].id= 0; //数据过大,离散化
temp= 0;
for( i=1; i<2*n; i++){
if( leaf[i].p!= leaf[i-1].p){ //离散时注意相同值节点
temp++;
hush[temp]= leaf[i].p;
}
leaf[i].id= temp;
}
mm= temp;
sort( leaf, leaf+ 2*n, cmp2);
}
void maketree( int lef, int rig, int num){ //建立线段树
tree[num].hei= 0;
tree[num].lef= lef;
tree[num].rig= rig;
tree[num].mid= ( lef+ rig)/2;
if( lef+1 != rig){
maketree( lef, tree[num].mid, num*2);
maketree( tree[num].mid, rig, num*2+1);
}
}
void insert( int lef, int rig, int hei, int num){ //插入
// cout<<hush[lef]<<" "<<hush[rig]<<" "<<hei<<" "<<num<<endl;
//cout<<lef<<" "<<rig<<endl;
if( lef== tree[num].lef && rig== tree[num].rig ){
tree[num].hei= max( tree[num].hei, hei);
return ;
}
if( rig<= tree[num].mid) //注意处理边界
insert( lef, rig, hei, 2*num);
else if( lef>= tree[num].mid)
insert( lef, rig, hei, 2*num+1);
else{
insert( lef, tree[num].mid, hei, num*2);
insert( tree[num].mid, rig, hei, num*2+1);
}
}
long long cal(int num, int h){ //求和
/*父节点一定可以覆盖子节点,由于更新线段树时,
遇见l==tree[num].lef && r== tree[num].rig时,
更新后即return,而未处理子节点,
所以存在父节点与子节点高度不同的情况,
若父节点高度大于子节点,则更新子节点高度为父节点值,
但可能存在子节点高度大于父的情况,故一定要到子节点才可计算面积*/
if( h> tree[num].hei) tree[num].hei= h;
if( tree[num].lef+1 == tree[num].rig)
return (long long)(hush[tree[num].rig]- hush[tree[num].lef] )*(long long )(tree[num].hei);
return cal( num*2, tree[num].hei) + cal( num*2+1, tree[num].hei);
}
int main(){
// freopen("1.txt", "r", stdin);
int i, j;
scanf("%d", &n);
init();
maketree( 0, mm, 1);
for( i=0; i<2*n; i+= 2){//cout<<i<<endl;
insert( leaf[i].id, leaf[i+1].id, height[i/2], 1);
}
printf("%lld\n", cal(1, -1));
return 0;
}