【线段树】City Horizon
来源:互联网 发布:非凡软件站安全吗 编辑:程序博客网 时间:2024/06/05 06:58
题意:给出一堆建筑物的左右端点(a,b),范围很大10^9,建筑物都是长方形的且可以相互覆盖,每个建筑物的高度是hi.求这些建筑物总共覆盖的面积。
思路:这题由于建筑物的个数比较多,4*10^4,所以如果暴力枚举o(n^2)的话,肯定会超时的。所以想到用线段树优化来寻找或者标记哪些建筑物相互覆盖,并且在那些建筑物上取相互覆盖中的高度较高者作为被覆盖部分的新的高度。用线段树来执行更改这个动作的话,时间复杂度是lgn的。又由于每个建筑物的左右端点坐标值可能很大,所以线段树的两端点不可能存那么大,也没必要,因为只有40000条线段。所以采用离散化的技术,即把这些大的端点值离散化成1-40000*2范围内的数来表示。建树也能建了。
离散化是一门技术,好的离散化方法在时间和代码复杂度上都很让人感到舒服满意。我离散化的技术不好,像这种是(a,b)成对出现的离散化,我只会用map来暴力,所以时间复杂度很高,不过编码复杂度到是简单。求大牛指教高效美观的离散化。
还有就是,我平时写线段树喜欢把端点写成[x,x]这种模样,不喜欢写成[x,x+1)这种。但这道题,我用前者写的时候,脑袋老是转不动,又想得越来越复杂。。囧。。因为涉及到离散化前后的映射问题。到时采用后者,在某一段端点被更新掉了的情况也不影响,处理很方便。理解不够深入惹的祸。。。
#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>#include<map>#include<vector>using namespace std;typedef long long LL;const int N = 40000 + 10;inline char Rstr(){char str[10];scanf("%s",str);return str[0];}map<LL,int>mp;int n;LL a[N],b[N],h[N];int hash[N*2];LL area;vector<LL>v;struct node{ int left,right; LL height;};node seg_tree[N*8];void creattree(int l,int r,int rt){ seg_tree[rt].left = l; seg_tree[rt].right = r; seg_tree[rt].height = 0; if(l+1==r) return; int mid = (l+r)>>1; creattree(l,mid,rt<<1); creattree(mid,r,rt<<1|1);}void insert(int l,int r,int h,int rt){ if(l==seg_tree[rt].left && r==seg_tree[rt].right) { if(seg_tree[rt].height<h || !seg_tree[rt].height) seg_tree[rt].height = h; return; } int mid = (seg_tree[rt].left + seg_tree[rt].right)>>1; if(mid>=r) insert(l,r,h,rt<<1); else if(mid<=l) insert(l,r,h,rt<<1|1); else { insert(l,mid,h,rt<<1); insert(mid,r,h,rt<<1|1); }}LL cal(int h,int rt){ if(h>seg_tree[rt].height) seg_tree[rt].height = h; if(seg_tree[rt].left+1==seg_tree[rt].right) return (hash[seg_tree[rt].right]-hash[seg_tree[rt].left]) *seg_tree[rt].height; return cal(seg_tree[rt].height,rt<<1) + cal(seg_tree[rt].height,rt<<1|1);}int main(){ while(scanf("%d",&n)==1) { mp.clear(); v.clear(); area=0; creattree(1,n*2,1); int k=1; for(int i=1;i<=n;i++) { scanf("%lld%lld%lld",&a[i],&b[i],&h[i]); v.push_back(a[i]); v.push_back(b[i]); } sort(v.begin(),v.end()); unique(v.begin(),v.end()); for(int i=0;i<v.size();i++) { if(!mp[v[i]]) { mp[v[i]]=k; hash[k++]=v[i]; } } for(int i=1;i<=n;i++) { //printf("%d %d\n",mp[a[i]],mp[b[i]]); insert(mp[a[i]],mp[b[i]],h[i],1); } area = cal(seg_tree[1].height,1); cout << area << endl; } return 0;}
- 【线段树】City Horizon
- 【POJ3277】City Horizon,线段树
- poj -- 3277City Horizon (线段树)
- poj3277 City Horizon(离散化+线段树)
- poj 3277 city horizon 线段树
- POJ 3277 City Horizon 线段树
- City Horizon poj3277 线段树+离散化
- poj 3277 City Horizon 线段树
- Poj 3277 City Horizon - 线段树
- TOJ 1706: City Horizon -- 线段树,平衡树
- pku 3277 City Horizon(离散化+线段树)
- PKU 3327City Horizon离散化+线段树
- (离散化 + 线段树) poj 3277 City Horizon
- poj 3277 City Horizon(线段树#2----离散化)
- HDU 3277 City Horizon(线段树 + 离散化)
- POJ 3277 City Horizon 扫描线+离散化+线段树
- poj-3277-City Horizon-离散化+线段树区域更新
- POJ 3277 City Horizon (离散化线段树)
- RIAPlayer播放器不能用的问题解决
- 骑士聚会问题
- 为什么中国的程序员技术偏低
- 点击改行table中的tr则变为红色其他变为白色
- 二叉排序树的建立以及相关操作 C语言
- 【线段树】City Horizon
- [ACM Collegiate PC 2011] Hunan
- hdu 2152 Fruit
- 我的linux(fedora)学习之路——从浮躁到踏实
- 选中复选框则显示内容否则不显示
- 关于容器中的算法
- 自动加载自定义类
- 有感于李开复演讲(2)
- 散热风扇