hdu1524线段树,扫描线
来源:互联网 发布:linux 时间格式 编辑:程序博客网 时间:2024/06/03 06:43
http://acm.hdu.edu.cn/showproblem.php?pid=1542
题意:
一些相互可能重叠的矩形,让你求他们实际覆盖的面积之和;
对于每个矩形,给你左上角坐标,以及右下角顶点坐标
#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int maxn=50009;//cnt记录此区间上的上面的边和下面的边条数之差int n,cnt[maxn<<2],tmp,res;//sum记录区间覆盖的长度double sum[maxn<<2];//x[]记录离散化以后的坐标double x[maxn];struct node{ //线段的左右两个端点的横坐标以及纵坐标 double a,b,h; //标记是矩形上面的边还是下面的边 int d; node(double x=0,double y=0,double z=0,int aa=0) { a=x,b=y,h=z,d=aa; }}line[maxn];int cmp(node a,node b){ return a.h<b.h;}void pushup(int rt){ sum[rt]=sum[rt<<1]+sum[rt<<1|1]; //cnt为-1代表此区间的边数覆盖并不是均匀的,也就是左右两个区间 //上下边的覆盖条数不一样 if(cnt[rt<<1]==-1||cnt[rt<<1|1]==-1) cnt[rt]=-1; else if(cnt[rt<<1]!=cnt[rt<<1|1]) cnt[rt]=-1; else cnt[rt]=cnt[rt<<1];}void pushdown(int rt,int l,int r){ int m=l+r>>1; if(cnt[rt]!=-1) { cnt[rt<<1]=cnt[rt<<1|1]=cnt[rt]; //如果边数覆盖均匀,则可以计算区间的覆盖长度 //注意区间长度计算时的端点选取 sum[rt<<1]=cnt[rt<<1]?x[m+1]-x[l]:0; sum[rt<<1|1]=cnt[rt<<1|1]?x[r+1]-x[m+1]:0; }}void build(int l,int r,int rt){ if(l==r) { sum[rt]=0; cnt[rt]=0; return; } int m=l+r>>1; build(lson); build(rson); pushup(rt);}void update(int L,int R,int val,int l,int r,int rt){ if(L<=l&&r<=R) { if(cnt[rt]!=-1) { //只有覆盖均匀的区间才可以直接加减更新 cnt[rt]+=val; sum[rt]=cnt[rt]?x[r+1]-x[l]:0; //注意return 在if里面 //如果区间不均匀则应该直到区间均匀分布后在更新 return; } } pushdown(rt,l,r); int m=l+r>>1; if(m>=L) update(L,R,val,lson); if(m<R) update(L,R,val,rson); pushup(rt);}int fin(double xx){ int l=1,r=tmp; while(l<=r) { int m=l+r>>1; if(x[m]==xx) return m; else if(xx>x[m]) l=m+1; else r=m-1; } return -1;}int main(){ int ase=1; while(scanf("%d",&n)&&n) { double a,b,c,d; res=1; for(int i=0;i<n;i++) { scanf("%lf%lf%lf%lf",&a,&b,&c,&d); x[res]=a; line[res++]=node(a,c,d,-1); x[res]=c; line[res++]=node(a,c,b,1); } sort(x+1,x+1+res); sort(line+1,line+1+res,cmp); tmp=1; //去重 for(int i=2;i<=res;i++) if(x[i]!=x[i-1]) x[++tmp]=x[i]; //注意这里,我们实际线段树维护的是区间标号,若有n个端点,则实际只有n-1个区间 build(1,tmp-1,1); double ss=0.0; for(int i=1;i<res;i++) { int l=fin(line[i].a); //注意这里要减一,得到的才是正确的区间标号 int r=fin(line[i].b)-1; if(l<=r) update(l,r,line[i].d,1,tmp-1,1); ss+=sum[1]*(line[i+1].h-line[i].h); } printf("Test case #%d\n",ase++); printf("Total explored area: %.2f\n\n",ss); } return 0;}
阅读全文
0 0
- hdu1524线段树,扫描线
- 线段树[扫描线]
- 线段树+扫描线
- 线段树 扫描线
- 线段树扫描线
- 线段树-扫描线
- hdu4007 线段树扫描线
- poj2482 线段树扫描线
- poj2464 线段树扫描线
- ural1707 线段树扫描线
- hdu4419 线段树扫描线
- hdu1828线段树+扫描线
- POJ1177+线段树+扫描线
- POJ1151+线段树+扫描线
- HDU3255(线段树+扫描线)
- 线段树扫描线upcoj2540
- 线段树之扫描线
- 线段树扫描线hdu4052
- Trading Terms
- 深入解析JavaScript闭包:从作用域与作用域链s
- Android Shape实现选择器样式
- OpenCV之Point、Scalar数据类及基本绘图
- Git-破晓
- hdu1524线段树,扫描线
- 蓝牙小试牛刀之蓝牙4.0BLE开发
- uikit——Auto Layout——layout margin
- std::cout 与 cout 有什么区别 // cout有些时候为什么前面要加std
- 通配符选择器子元素选择器后代选择器
- 关于umask,perror,strerror和如何输出有颜色字
- 质因数分解
- python使用optparse模块实现wc命令(二)
- uikit——Auto Layout——Readable Content Guide