POJ 3277 City Horizon(叶子节点为[a,a+1)的线段树+离散化)
网上还有用unique函数和lowerbound函数离散的方法,可以百度搜下题解就有。
这里给出介绍unique函数的链接:http://www.cnblogs.com/zhangshu/archive/2011/07/23/2115090.html
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <set>
/*
题意:
给出一条直线上的矩形左右坐标和高度,求所有矩形并的面积。
思路:
这里处理没有跟以前的线段树一样,这里每个叶子节点代表的是区间[a,a+1),而不像以前的代表一个点(a,a);
需要建立基本单位为线段的线段树,建法与以点为单位的线段树就一点点不同,具体见代码。这样可以方便在离散化后求一段区间间的长度 由于A、B的值太大,需要离散。且不可能开那么大的数组,也就不能通过A、B直接获取他们的映射值。
而只能通过他们映射的值来获取对应的A、B,用二分查找。
由于最后求并的面积,为方便起见,可以先将矩形按高度从小到大排序,后面的覆盖前面的即可。 在discuss里别人写的几个注意点:
总算有点收获,总结以下几点
1、离散的时候要用二分来查找映射值
2、数据全部用long long 吧,比较保险
3、数组开大点,因为一共有40000组数据,每组数据两个点,加起来也就是有大约80000个点,所以N要开到80000,存线段树的数组要开到4*N。
4、题目的意思是要算矩形和,也就是说同一个线段上有多个高度的话,取最高的那个,再modify的时候,
可以先对输入的数据根据高度从小到大排序,在接下来的操作中直接覆盖,这样就可以避免一些不必要的麻烦。 */
using namespace std;
const int maxn=;
int n;
int cnt;
long long vk[maxn*]; //vk[i]=A,表示A映射的值为i,要通过二分查找,寻找A对应的映射值
long long val[maxn*];
struct Tree{
long long sum; //该区间的矩阵面积
long long num; //该区间的矩阵高度
bool lazy;
}tree[maxn<<];
struct Node{
long long a,b,h; //区间[a,b],以及高度h
bool operator<(const Node tmp)const{
return h<tmp.h;
}
}node[maxn]; //二分查找k对应的映射值
int binsearch(long long k){
int l=,r=cnt,mid;
while(l<=r){
mid=(l+r)>>;
if(vk[mid]==k)
return mid;
if(vk[mid]<k)
l=mid+;
else
r=mid-;
}
return -; //肯定会查找的到,这里就是摆设
} void build(int rt,int L,int R){
tree[rt].sum=;
tree[rt].num=;
tree[rt].lazy=false;
if(L+==R) //这才是重点啊,建立区间为[a,a+1)的叶子节点
return;
int mid=(L+R)>>;
build(rt<<,L,mid);
build(rt<<|,mid,R); //右儿子:mid~R
} void pushUp(int rt){
tree[rt].sum=(tree[rt<<].sum+tree[rt<<|].sum);
} void pushDown(int rt,int L,int R){
if(tree[rt].lazy){
int lson=rt<<,rson=rt<<|;
int mid=(L+R)>>;
long long l1=vk[L],r1=vk[mid],l2=vk[mid],r2=vk[R],length1,length2;
tree[lson].num=tree[rson].num=tree[rt].num;
length1=r1-l1;length2=r2-l2; //左儿子对应的区间长度和右儿子对应的区间长度
tree[lson].sum=length1*tree[rt].num;
tree[rson].sum=length2*tree[rt].num;
tree[lson].lazy=tree[rson].lazy=true;
tree[rt].lazy=false;
}
}
//L,R是节点rt的区间,l,r是要更新的区间目标
void update(int rt,int L,int R,int l,int r,long long h){
long long left=vk[L],right=vk[R],length;
if(l<=L && R<=r){
tree[rt].num=h;
length=right-left;
tree[rt].sum=h*length;
tree[rt].lazy=true;
return;
}
pushDown(rt,L,R);
int mid=(L+R)>>;
//注意两个if条件里面不能有等号
if(l<mid)
update(rt<<,L,mid,l,r,h);
if(r>mid)
update(rt<<|,mid,R,l,r,h);
//也可以下面注释的语句
/*
if(r<=mid)
update(rt<<1,L,mid,l,r,h);
else if(l>=mid)
update(rt<<1|1,mid,R,l,r,h);
else{
update(rt<<1,L,mid,l,mid,h);
update(rt<<1|1,mid,R,mid,r,h);
}
*/
pushUp(rt);
}
int main()
{
long long a,b,h;
int idx=;
scanf("%d",&n);
for(int i=;i<n;i++){
scanf("%I64d%I64d%I64d",&a,&b,&h);
node[i].a=a;
node[i].b=b;
node[i].h=h;
val[idx++]=a;
val[idx++]=b;
}
//离散化
sort(val,val+idx);
cnt=;
vk[cnt]=val[];
for(int i=;i<idx;i++){
if(val[i]==val[i-])
continue;
vk[++cnt]=val[i]; //只不过这里建立的是映射————key
} build(,,cnt);
sort(node,node+n);
int x,y;
for(int i=;i<n;i++){
//二分查找,获取映射
x=binsearch(node[i].a);
y=binsearch(node[i].b);
//printf("%I64d %I64d: %d %d\n",node[i].a,node[i].b,x,y);
update(,,cnt,x,y,node[i].h);
}
printf("%I64d\n",tree[].sum);
return ;
}
POJ 3277 City Horizon(叶子节点为[a,a+1)的线段树+离散化)的更多相关文章
- 离散化+线段树 POJ 3277 City Horizon
POJ 3277 City Horizon Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 18466 Accepted: 507 ...
- [POJ] 3277 .City Horizon(离散+线段树)
来自这两篇博客的总结 http://blog.csdn.net/SunnyYoona/article/details/43938355 http://m.blog.csdn.net/blog/mr_z ...
- poj 3277 City Horizon (线段树 扫描线 矩形面积并)
题目链接 题意: 给一些矩形,给出长和高,其中长是用区间的形式给出的,有些区间有重叠,最后求所有矩形的面积. 分析: 给的区间的范围很大,所以需要离散化,还需要把y坐标去重,不过我试了一下不去重 也不 ...
- POJ 3277 City Horizon(扫描线+线段树)
题目链接 类似求面积并..2Y.. #include <cstdio> #include <cstring> #include <string> #include ...
- POJ 3277 City Horizon
标题效果: 每间房子的长度给出阴影(在间隔代表)而高度,求阴影总面积. 解题思路:矩形面积并. 以下是代码: #include <set> #include <map> #in ...
- POJ 2528 Mayor's posters(线段树+离散化)
Mayor's posters 转载自:http://blog.csdn.net/winddreams/article/details/38443761 [题目链接]Mayor's posters [ ...
- poj 2528 Mayor's posters(线段树+离散化)
/* poj 2528 Mayor's posters 线段树 + 离散化 离散化的理解: 给你一系列的正整数, 例如 1, 4 , 100, 1000000000, 如果利用线段树求解的话,很明显 ...
- poj 2528 Mayor's posters 线段树+离散化技巧
poj 2528 Mayor's posters 题目链接: http://poj.org/problem?id=2528 思路: 线段树+离散化技巧(这里的离散化需要注意一下啊,题目数据弱看不出来) ...
- 【POJ 2482】 Stars in Your Window(线段树+离散化+扫描线)
[POJ 2482] Stars in Your Window(线段树+离散化+扫描线) Time Limit: 1000MS Memory Limit: 65536K Total Submiss ...
随机推荐
- 南阳理工oj88--汉诺塔(一)
题目链接.http://acm.nyist.net/JudgeOnline/problem.php?pid=88 #include <stdio.h> /* //测试一下49999和500 ...
- C++ Stacks(堆栈)
C++ Stack(堆栈) 是一个容器类的改编,为程序员提供了堆栈的全部功能,——也就是说实现了一个先进后出(FILO)的数据结构. 操作 比较和分配堆栈 empty() 堆栈为空则返回真 pop() ...
- 阿里巴巴2013年实习生笔试题A
一.单项选择题 1.下列说法不正确的是:(B) A.SATA硬盘的速度速度大约为500Mbps/s B.读取18XDVD光盘数据的速度为1Gbps C.前兆以太网的数据读取速度为1Gpbs D.读取D ...
- 探索VS中C++多态实现原理
引言 最近把<深度探索c++对象模型>读了几遍,收获甚大.明白了很多以前知其然却不知其所以然的姿势.比如构造函数与拷贝构造函数什么时候被编译器合成,虚函数.实例函数.类函数的区别等等.在此 ...
- FPGA/CPLD设计思想与技巧
本文讨论的四种常用FPGA/CPLD设计思想与技巧:乒乓操作.串并转换.流水线操作.数据接口同步化,都是FPGA/CPLD逻辑设计的内在规律的体现,合理地采用这些设计思想能在FPGA/CPLD设计工作 ...
- MATLAB light material lighting
clf;[X,Y,Z]=sphere(40);colormap(jet)subplot(1,2,1),surf(X,Y,Z),axis off square,shading interplight(' ...
- 【原】WinForm中的DataGridView加入Combbox或者DropDownButton后,操作变慢
DataGridView里加入了DropDownButto列,加载数据后点击这一列,反应很慢;要点击三到四次才会展示下拉列表; 原因是DataGridView的EditMode设置问题; 将DataG ...
- margin的BUG
在进行简单的div盒子嵌套时,发现设置margin-top时存在bug,然后就去谷歌搜索了一下,发现margin确实存在bug. bug的现象是父子元素嵌套时,如果子元素是块元素时,对块元素设置mar ...
- laravel--为什么属性在模型中没有定义,却取出来了值,这些属性哪里来的
看laravel模型中的这段代码, public function getLimitUsersAttribute() { return $this->user_limit - $this-> ...
- 使用jQuery获取GridView的数据行的数量
一个同事在群里抛出了上述的问题,另一个同事给出了答案,试了一下,还不错.贴出代码和效果图: <html xmlns="http://www.w3.org/1999/xhtml" ...