hdu 1255 面积交
来源:互联网 发布:开机client mac addr 编辑:程序博客网 时间:2024/05/01 01:57
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255
方法:离散化,线段树,扫描线
代码:
/**以y轴为扫描线然后用x[]记录下所有的x坐标,并对x坐标去重对于每一条扫描线xl, xr都二分找到在数组x[]的下标在用线段树更新的时候每次找到更新可以的区间的时候用pushdown(),更新到底并且用pushup()往上更新*/#include <iostream>#include <cstdio>#include <algorithm>using namespace std;#define maxn 2005struct Line{ double xl, xr, y; int cover; Line(){} Line(double xl, double xr, double y, int cover): xl(xl), xr(xr), y(y), cover(cover){} bool operator < (const Line& b)const { return y<b.y; }}line[maxn];double x[maxn];struct node{ int l, r, cover; double sum;}v[maxn<<2];void build(int l, int r, int n){ v[n].l = l, v[n].r = r; v[n].sum = 0; v[n].cover = 0; if (l==r) return ; int mid = (l+r) >> 1; build(l, mid, n<<1); build(mid+1, r, n<<1|1);}int find(double key, int n){ int l = 1, r = n, mid; while (l<=r) { mid = (l+r) >> 1; if (x[mid]==key) return mid; else if (x[mid]>key) r = mid-1; else l = mid+1; }}void pushup(int n){ v[n].sum = v[n<<1].sum + v[n<<1|1].sum;}void pushdown(int l, int r, int n, int cover){ v[n].cover += cover; if (l==r) { if (v[n].cover>1) v[n].sum = x[r+1] - x[r]; else v[n].sum = 0; return ; } int mid = (l + r) >> 1; pushdown(l, mid, n<<1, cover); pushdown(mid+1, r, n<<1|1, cover); pushup(n);}void update(int n, int l, int r, int cover){ if (l<=v[n].l && v[n].r<=r) { pushdown(v[n].l, v[n].r, n, cover);//更新到底,然后从底统计上来 return ; } int mid = (v[n].l + v[n].r) >> 1; if (r<=mid) update(n<<1, l, r, cover); else if (l>mid) update(n<<1|1, l, r, cover); else { update(n<<1, l, mid, cover); update(n<<1|1, mid+1, r, cover); } pushup(n);}int main(){ int ncase, n; scanf("%d", &ncase); while (ncase--) { scanf("%d", &n); int num = 0; for (int i=0; i<n; ++i) { double x1, x2, y1, y2; scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2); line[++num] = Line(x1, x2, y1, 1); x[num] = x1; line[++num] = Line(x1, x2, y2, -1); x[num] = x2; } sort(x+1, x+num+1); sort(line+1, line+num+1); n = 1; for (int i=2; i<=num; ++i)//去除相同的点 if (x[i]>x[i-1]) x[++n] = x[i]; double ans = 0; build(1, n, 1); for (int i=1; i<num; ++i) { int l = find(line[i].xl, n); int r = find(line[i].xr, n)-1; update(1, l, r, line[i].cover); ans += v[1].sum * (line[i+1].y - line[i].y); } printf("%.2f\n", ans); } return 0;}
#include <iostream>#include <cstdio>#include <algorithm>using namespace std;#define maxn 2005struct Line{ double xl, xr, y; int cover; Line(){} Line(double xl, double xr, double y, int cover): xl(xl), xr(xr), y(y), cover(cover){}; bool operator < (const Line& b)const { return y<b.y; }}line[maxn];double x[maxn];struct node{ int l, r, cover; double sum;//被覆盖两次及两次以上的长度 double cnt;//被覆盖一次及一次以上的长度 double xl, xr;}v[maxn<<2];int find(double key, int n){ int l = 1, r = n, mid; while (l<=r) { mid = (l+r) >> 1; if (x[mid]==key) return mid; else if (x[mid]>key) r = mid-1; else l = mid+1; }}void build(int l, int r, int n){ v[n].l = l, v[n].r = r; v[n].xl = x[l], v[n].xr = x[r]; v[n].cover = 0; v[n].sum = v[n].cnt = 0; if (l+1==r)//这里不是l==r return; int mid = (v[n].l + v[n].r) >> 1; build(l, mid, n<<1); build(mid, r, n<<1|1);//这里不是mid+1}void pushup(int n)//往上更新时分情况考虑{ if (v[n].cover>=2) { v[n].sum = v[n].xr - v[n].xl; v[n].cnt = v[n].xr - v[n].xl; } else if (v[n].cover == 1) { v[n].cnt = v[n].xr - v[n].xl; if (v[n].l+1==v[n].r) v[n].sum = 0; else v[n].sum = v[n<<1].cnt + v[n<<1|1].cnt;//这里注意 } else { if (v[n].l+1==v[n].r) v[n].sum = v[n].cnt = 0; else { v[n].sum = v[n<<1].sum + v[n<<1|1].sum; v[n].cnt = v[n<<1].cnt + v[n<<1|1].cnt; } }}void update(int n, int l, int r, int cover){ if (l<=v[n].l && v[n].r<=r) { v[n].cover += cover; pushup(n); return ; } int mid = (v[n].l + v[n].r) >> 1; if (r<=mid) update(n<<1, l, r, cover); else if (l>=mid) update(n<<1|1, l, r, cover); else { update(n<<1, l, mid, cover); update(n<<1|1, mid, r, cover); } pushup(n);}int main(){ int ncase, n; scanf("%d", &ncase); while (ncase--) { scanf("%d", &n); int num = 0; for (int i=0; i<n; ++i) { double x1, x2, y1, y2; scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2); line[++num] = Line(x1, x2, y1, 1); x[num] = x1; line[++num] = Line(x1, x2, y2, -1); x[num] = x2; } sort(x+1, x+num+1); sort(line+1, line+num+1); n = 1; for (int i=2; i<=num; ++i) if (x[i]>x[i-1]) x[++n] = x[i]; double ans = 0; build(1, n, 1); for (int i=1; i<num; i++) { int l = find(line[i].xl, n); int r = find(line[i].xr, n); update(1, l, r, line[i].cover); ans += v[1].sum * (line[i+1].y - line[i].y); } printf("%.2f\n", ans); } return 0;}
- hdu 1255 面积交
- HDU 1255 矩形面积交
- hdu 1255 矩形面积交
- hdu 1542 ,1255 线段树面积并与面积交
- hdu 1255 覆盖的面积(矩形面积二次交)
- HDU 1255 覆盖的面积(矩形交的面积)
- hdu 1255 覆盖的面积 矩阵面积交
- HDU 1255 覆盖的面积(线段树+面积交)
- hdu 1255 线段树 求矩形面积的交
- HDU 1255 线段树扫描线面积交
- hdu 1542 1255 1828 线段树矩阵并面积 交面积 重叠周长解法
- HDU 1255 - 覆盖的面积 (线段树 扫描线 面积交)
- HDU 1255 覆盖的面积(线段树扫描线求面积的交)
- hdu(1255)——覆盖的面积(线段树求面积交)
- HDU 1255 覆盖的面积(线段树求矩形面积交)
- hdu 1255 覆盖的面积(线段树 面积交+离散化)
- HDU 1255 覆盖的面积 (线段树扫描线+面积交)
- hdu 1255 覆盖的面积(线段树+扫描线——面积交)
- C++ 指针 引用 数组 详解
- Kendo UI开发教程(20): Kendo MVVM 数据绑定(九) Text
- [Makefile]Android.mk中打印变量
- 操作系统--对操作系统的研究
- CY7C68013A EEPROM烧写
- hdu 1255 面积交
- Kendo UI开发教程(21): Kendo MVVM 数据绑定(十) Source
- 基于shader的效果框架
- Java的extends用法
- Kendo UI开发教程(22): Kendo MVVM 数据绑定(十一) Value
- 二叉排序树的插入、查找、删除、遍历(C语言版)
- GitHub上最火的40个iOS开源项目
- python 批量改文件名称
- Kendo UI开发教程(23): 单页面应用(一)概述