poj 1151 Atlantis(多矩形面积) + poj 1177Picture(多矩形周长) 线段树进阶
来源:互联网 发布:淘宝代销怎么关联宝贝 编辑:程序博客网 时间:2024/06/06 06:37
题意:平面内有很多矩形,求它们组成的图形的总面积;
题解:
先将清楚一个东西,我用的扫描线是一根平行y轴的线,从左到右扫描(你也可以用一根横向的扫描线从下到上扫描),离散化就是把这跟线上的点hash一下;
1: 什么是离散化,其实很简单不要被这三个陌生的字给吓到了,这题我用的是将在y轴的点线离散化 ;
比如有y轴上有4个坐标分别是1, 30, 1000, 100000;按照一般的建树要从 1~100000;
离散化意思就是将于他们hash一下1还是1,30看成是2,1000看成3, 100000看成4,然后建树就变成了1~4;
巨大的节省了时间和空间;
poj 1151求面积这题有坐标是小数,你只能离散化建树;
下面再来看看扫描线:http://www.cnblogs.com/Booble/archive/2010/10/10/1847163.html(很详细,是求的周长);
不想讲了,其实会求周长了,就肯定会求面积了;
先看下这个:
struct TreeLines { int nLines;//这个区间里包括的线段的数量 int lLines;//这个区间左端点是否被覆盖; int rLines;//右端点是否被覆盖; //上面两个没其他用,就是辅助对nLines的计算的,先别想太多; int cover;//当前区间被覆盖的次数,其实也是用来辅助计算的 int m;//测度(意思就是这个区间里被覆盖线段的总和)} tree[8*MAXN];
注意:还有一个建树问题,别那样建,要这样建,哈哈哈!
还有就是当要插入或删除的线段x值相等时,要先插入再删除;因为如果两个矩形相邻,重合的那条边是不计入总周长的;
代码:
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;#define lson k<<1, l, mid, ff#define rson k<<1|1, mid, r, ffconst int MAXN = 5002;//要插入或删除的线段;struct Lines { int x, y1, y2, flag;//flag=1表示要插入的线段,-1表示要删除的; Lines(int a, int b, int c, int d):x(a),y1(b),y2(c),flag(d){} Lines(){}} lines[2*MAXN];//扫描线(线段树)struct TreeLines { int lLines, rLines, cover, m, nLines;} tree[8*MAXN];int yID[2*MAXN];//hash//更新mvoid updataM(int k, int l, int r) { if (tree[k].cover > 0) tree[k].m = yID[r]-yID[l]; else { if (r-l == 1) tree[k].m = 0; else tree[k].m = tree[k<<1].m + tree[k<<1|1].m; }}//更新nLines,实际上是3个变量一起更新void updataN(int k, int l, int r) { if (tree[k].cover > 0) tree[k].lLines = tree[k].nLines = tree[k].rLines = 1; else { if (r-l == 1) tree[k].lLines = tree[k].nLines = tree[k].rLines = 0; else { int ll = k<<1, rr = k<<1|1; tree[k].lLines = tree[ll].lLines; tree[k].rLines = tree[rr].rLines; tree[k].nLines = tree[ll].nLines+tree[rr].nLines-(tree[ll].rLines&tree[rr].lLines); } }}void query(int li, int ri, int k, int l, int r, int ff) { if (li <= yID[l] && ri >= yID[r]) { tree[k].cover += ff; } else if (r-l > 1){//我说是这样建树 int mid = (l+r)/2; if (li < yID[mid]) query(li, ri, lson); if (ri > yID[mid]) query(li, ri, rson); } //这里比较重要是回归的时候更新值;(第一次做这样的) updataM(k, l, r); updataN(k, l, r);}int cmp(Lines aa, Lines bb) { if (aa.x == bb.x) return aa.flag > bb.flag;//这里注意,先要插入,在删除 else return aa.x < bb.x;}int main() { int x1, x2, y1, y2, j = 1, T; scanf("%d", &T); memset(tree, 0, sizeof(tree)); while (T--) { scanf("%d%d%d%d", &x1, &y1, &x2, &y2); lines[j] = Lines(x1, y1, y2, 1); yID[j++] = y1; lines[j] = Lines(x2, y1, y2, -1); yID[j++] = y2; } sort(yID+1, yID+j); int k = 1; for(int i = 1; i < j; i++) {//删除重复节点 yID[k++] = yID[i]; while (yID[i] == yID[i+1]) i++; } sort(lines+1, lines+j, cmp); int res = 0, preN, preM = 0; for(int i = 1; i < j; i++) {//一个区间,一个区间的求; query(lines[i].y1, lines[i].y2, 1, 1, k-1, lines[i].flag); if (i > 1) res += preN*2*(lines[i].x-lines[i-1].x); res += abs(preM-tree[1].m); preM = tree[1].m; preN = tree[1].nLines; } printf("%d\n", res); return 0;}
求面积的话,就只要更新测度m了;
代码:
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;#define lson k<<1, l, mid, ff#define rson k<<1|1, mid, r, ffconst int MAXN = 102;struct Lines { float x, y1, y2; int flag; Lines(float a, float b, float c, int d):x(a),y1(b),y2(c),flag(d){} Lines(){}} lines[2*MAXN];struct TreeLines { int cover; float m;} tree[8*MAXN];float yID[2*MAXN];void updataM(int k, int l, int r) { if (tree[k].cover > 0) tree[k].m = yID[r]-yID[l]; else { if (r-l == 1) tree[k].m = 0; else tree[k].m = tree[k<<1].m + tree[k<<1|1].m; }}void query(float li, float ri, int k, int l, int r, int ff) { if (li <= yID[l] && ri >= yID[r]) { tree[k].cover += ff; } else if (r-l > 1){ int mid = (l+r)/2; if (li < yID[mid]) query(li, ri, lson); if (ri > yID[mid]) query(li, ri, rson); } updataM(k, l, r);}int cmp(Lines aa, Lines bb) { if (aa.x == bb.x) return aa.flag > bb.flag; else return aa.x < bb.x;}int main() { float x1, x2, y1, y2; int j, T, tt = 1; while(scanf("%d", &T) && T) { memset(tree, 0, sizeof(tree)); j = 1; while (T--) { scanf("%f%f%f%f", &x1, &y1, &x2, &y2); lines[j] = Lines(x1, y1, y2, 1); yID[j++] = y1; lines[j] = Lines(x2, y1, y2, -1); yID[j++] = y2; } sort(yID+1, yID+j); int k = 1; for(int i = 1; i < j; i++) { yID[k++] = yID[i]; while (yID[i] == yID[i+1]) i++; } sort(lines+1, lines+j, cmp); float preM = 0; double res = 0; for(int i = 1; i < j; i++) { query(lines[i].y1, lines[i].y2, 1, 1, k-1, lines[i].flag); if (i > 1) res += preM*(lines[i].x-lines[i-1].x); preM = tree[1].m; } printf("Test case #%d\nTotal explored area: %.2f\n\n", tt++, res); } return 0;}
0 0
- poj 1151 Atlantis(多矩形面积) + poj 1177Picture(多矩形周长) 线段树进阶
- poj 1177 Picture(线段树求矩形周长并)
- poj 1151 线段树+扫描线(Atlantis矩形面积)
- poj 1177 Picture(线段树+矩形周长并)
- POJ-1177 Picture (线段树 求矩形周长)
- POJ 1151 Atlantis 线段树/矩形面积并
- Hdu 1542/ POj 1151 Atlantis 线段树+矩形面积并
- POJ 1151 Atlantis (线段树求矩形面积并)
- poj-1177 Picture(矩形周长并,线段树+扫描线)
- zoj 1128 || poj 1151 Atlantis(线段树求矩形面积并)
- poj 1151 Atlantis(矩形面积并,线段树+离散化)
- POJ 1151 Atlantis (线段树+扫描线 求矩形面积并)
- POJ-1151-Atlantis-求矩形面积并(线段树+扫描线)
- POJ 1177 Picture(矩形并的周长)
- POJ 1177 Picture 矩形周长并
- POJ 1177 Picture 求多个矩形周长 -
- 矩形面积并 poj 1151Atlantis
- poj 1151 Atlantis 纯矩形面积并
- 索引
- Servlet--2.filter
- jersey加spring加mybatis整合
- 资源网站
- 剑指offer--树的子结构
- poj 1151 Atlantis(多矩形面积) + poj 1177Picture(多矩形周长) 线段树进阶
- uva 12661 Funny Car Racing
- Ftp上传下载
- eclipse中Tomcat的配置
- Nuttx编译系统
- 聊聊传统算法系统和机器学习系统的一点不同
- MATLAB中accumarray函数详解
- eclipse导出Java文件为.exe可执行文件
- 数据分析随笔