POJ 3277 City Horizon
2012-08-02 23:40
197 查看
POJ 3277 City Horizon
线段树+离散化+矩形面积。初次写这类题目,用了很长时间才搞明白其中的很多问题。这个题目是线段树+离散化+矩形面积中比较简单的了。
首先如何求解矩形面积。
求解矩形面积很简单:直接套用公式:长乘以宽,可是在这里矩形与矩形间有重叠,该怎么处理呢?矩形与矩形相交的边,我们可以找出来,那么求解矩形面积不就好求了么。由于本题中有一边是x轴,所以我们只要处理出每个高度所对应的矩形的两条平行y轴的边即可,也就是说我们只要找到矩形的x坐标就可以了。我们利用线段树来求解。我们以x坐标来建线段树,将高度也即y坐标做为线段树中的值,然后不断的插入即可。换句话说也就是不断的向区间(x1
, x2)中加某个数h,其中(x1 , x2)就是原矩形的x坐标,而h即是对应的高度。插入的时候不断的更新h值。最后直接用公式统计就可以了。
矩形的x坐标范围很大怎么处理?
离散化。由于我们的边只有40000个左右,如果离散化就可以存储下了。那怎么离散化?我们将x坐标全部加入到一个数组中,然后对x坐标由小到达进行排序,然后对于每个左边都对应一个下标,我们只需要对这个下标进行建树就可了。这样离散化就不会产生矩形的宽度等问题了。
在插入的时候,可能会差生覆盖问题。(想想为什么?)有两种解决办法:1.在查询的时候我们可以每次查询到叶子节点。2.插入前对高度进行排序(由小到大)。建议自己模拟手算一下。
方法一:
方法2:
线段树+离散化+矩形面积。初次写这类题目,用了很长时间才搞明白其中的很多问题。这个题目是线段树+离散化+矩形面积中比较简单的了。
首先如何求解矩形面积。
求解矩形面积很简单:直接套用公式:长乘以宽,可是在这里矩形与矩形间有重叠,该怎么处理呢?矩形与矩形相交的边,我们可以找出来,那么求解矩形面积不就好求了么。由于本题中有一边是x轴,所以我们只要处理出每个高度所对应的矩形的两条平行y轴的边即可,也就是说我们只要找到矩形的x坐标就可以了。我们利用线段树来求解。我们以x坐标来建线段树,将高度也即y坐标做为线段树中的值,然后不断的插入即可。换句话说也就是不断的向区间(x1
, x2)中加某个数h,其中(x1 , x2)就是原矩形的x坐标,而h即是对应的高度。插入的时候不断的更新h值。最后直接用公式统计就可以了。
矩形的x坐标范围很大怎么处理?
离散化。由于我们的边只有40000个左右,如果离散化就可以存储下了。那怎么离散化?我们将x坐标全部加入到一个数组中,然后对x坐标由小到达进行排序,然后对于每个左边都对应一个下标,我们只需要对这个下标进行建树就可了。这样离散化就不会产生矩形的宽度等问题了。
在插入的时候,可能会差生覆盖问题。(想想为什么?)有两种解决办法:1.在查询的时候我们可以每次查询到叶子节点。2.插入前对高度进行排序(由小到大)。建议自己模拟手算一下。
方法一:
#include <iostream> #include <string.h> #include <stdio.h> #include <algorithm> using namespace std ; const int maxn = 40100 ; struct Line{ int x ; int y ; int h ; }; struct SegmentTree{ int l ; int r ; int h ; }; Line line[maxn] ; SegmentTree tree[300000] ; int Sline[maxn * 2] ; int n ; int inline M(int x , int y){ return (x + y) >>1 ; } int inline L(int x){ return x<<1 ; } int inline R(int x){ return x<<1|1 ; } void build(int l , int r , int c){ tree[c].l = l ; tree[c].r = r ; tree[c].h = 0 ; if(l + 1 == r) return ; build( l , M(l , r) , L(c)) ; build( M(l , r) , r , R(c)) ; } void insert(int l , int r , int c , int h){ if(Sline[ tree[c].l ] == l && Sline[ tree[c].r ] == r){ if(tree[c].h < h) tree[c].h = h ; return ; } int m = M( tree[c].l , tree[c].r) ; if(r <= Sline[m]) insert(l , r , L(c) , h) ; else if(l >= Sline[m]) insert(l , r , R(c) , h) ; else{ insert(l , Sline[m] , L(c) , h) ; insert(Sline[m] , r , R(c) , h) ; } } void query(long long &ans , int h , int c){ if(tree[c].h > h){ h = tree[c].h ; } if(tree[c].l + 1 == tree[c].r){ ans += (long long)(Sline[ tree[c].r ] - Sline[ tree[c].l ]) * h ; return ; } query( ans , h , L(c)) ; query( ans , h , R(c)) ; } int main(){ int x ; int y ; int w ; int t ; scanf("%d" , &n) ; t = 0 ; for(int i = 1 ; i <= n ; i ++){ scanf("%d%d%d" , &x , &y , &w) ; line[i].x = x ; line[i].y = y ; line[i].h = w ; Sline[ ++ t] = x ; Sline[ ++ t] = y ; } sort(Sline + 1 , Sline + t + 1) ; t = unique(Sline + 1 , Sline + t + 1) - Sline - 1 ; build(1 , t , 1) ; for(int i = 1 ; i <= n ; i ++){ insert(line[i].x , line[i].y , 1 , line[i].h ) ; } long long ans = 0 ; query(ans , 0 , 1) ; printf("%lld\n" , ans) ; return 0 ; }
方法2:
//Accepted 4032K 266MS #include <iostream> #include <string.h> #include <stdio.h> #include <algorithm> using namespace std ; const int maxn = 40010 ; struct Line{ int x ; int y ; int h ; }; struct SegmentTree{ int l ; int r ; int h ; }; bool cmp(Line a , Line b){ return a.h < b.h ; } Line line[maxn] ; SegmentTree tree[maxn * 8] ; int Sline[maxn * 2] ; int n ; int m ; int inline M(int x , int y){ return (x + y)>>1 ; } int inline L(int x){ return x<<1 ; } int inline R(int x){ return x<<1|1 ; } void build(int l , int r , int c){ tree[c].l = l ; tree[c].r = r ; tree[c].h = 0 ; if(l + 1 == r) return ; build(l , M(l , r) , L(c)) ; build(M(l , r) , r , R(c)) ; } void pushdown(int c){ int l = L(c) ; int r = R(c) ; if(tree[c].h == 0) return ; if(tree[c].h > tree[l].h) tree[l].h = tree[c].h ; if(tree[c].h > tree[r].h) tree[r].h = tree[c].h ; tree[c].h = 0 ; } void insert(int l , int r , int h ,int c){ if(tree[c].h > h) return ; if(Sline[ tree[c].l ] == l && Sline[ tree[c].r ] == r){ tree[c].h = h ; return ; } if(tree[c].l + 1 == tree[c].r) return ; pushdown(c) ; int m = M(tree[c].l , tree[c].r) ; if(r <= Sline[m]) return insert(l , r , h , L(c)) ; if(l >= Sline[m]) return insert(l , r , h , R(c)) ; insert(l , Sline[m] , h , L(c)) ; insert(Sline[m] , r , h , R(c)) ; } void query(long long & ans , int c){ if(tree[c].h != 0){ ans += (long long)(Sline[ tree[c].r ] - Sline[ tree[c].l ]) * tree[c].h ; return ; } if(tree[c].l + 1 == tree[c].r) return ; query(ans , L(c)) ; query(ans , R(c)) ; } int main(){ scanf("%d" , &n) ; m = 0 ; for(int i = 0 ; i < n ; i ++){ scanf("%d%d%d" , &line[i].x , &line[i].y , &line[i].h) ; Sline[++m] = line[i].x ; Sline[++m] = line[i].y ; } sort(Sline + 1 , Sline + m + 1) ; sort(line , line + n , cmp) ; // for(int i = 0 ; i < n ; i ++){ // printf("%d %d %d\n" , line[i].x , line[i].y , line[i].h) ; // } m = unique(Sline + 1 , Sline + m + 1) - Sline - 1 ; build(1 , m , 1) ; for(int i = 0 ; i < n ; i ++){ insert(line[i].x , line[i].y , line[i].h , 1) ; } long long ans = 0 ; query(ans , 1) ; printf("%lld\n" , ans) ; return 0 ; }
相关文章推荐
- poj 3277 City Horizon
- 【线段树】 POJ 3277 City Horizon 裸扫描线
- POJ 题目3277 City Horizon(线段树+离散化+扫描线)
- #POJ 3277 City Horizon 【离散化、区间更新】
- 【线段树】 POJ 3277 City Horizon 裸扫描线
- [POJ 3277]City Horizon
- POJ 3277 City Horizon (离散化线段树)
- poj 3277 City Horizon
- POJ 3277 City Horizon【map模板】【stl练习】
- POJ 3277 City Horizon(扫描线+线段树)
- POJ 3277 City Horizon
- poj-3277-City Horizon-离散化+线段树区域更新
- POJ 3277 City Horizon
- poj 3277 City Horizon
- POJ 3277 City Horizon 扫描线+离散化+线段树
- POJ训练计划3277_City Horizon(扫描线/线段树+离散)
- (离散化 + 线段树) poj 3277 City Horizon
- poj 3277 City Horizon 线段树
- POJ 3277 - City Horizon
- poj 3277 city horizon 线段树