HDU - 1255 覆盖的面积(线段树 扫描线)
2015-10-21 11:13
399 查看
题目大意:中文题
解题思路:记录区间被cover的次数,区间的被cover1次的长度len,区间被cover2次或者2次以上的长度twice
所要求的覆盖面积,就是求被cover两次或者两次以上的长度 * 高的和
首先判断是否被cover过,先更新一下len
1.接着判断一下是否被cover过次或者两次以上,如果符合,直接等于右端点-左端点
2.如果不符合条件1,且l == r ,那么twice = 0
3.如果不符合2,但是满足cover == 1,那么twice[u] = len[u << 1] + len[u << 1 | 1], 因为左右区间被覆盖一次的长度会被再覆盖一次
4.如果不符合条件3,twice[u] = twice[u << 1] + twice[u << 1 | 1]
解题思路:记录区间被cover的次数,区间的被cover1次的长度len,区间被cover2次或者2次以上的长度twice
所要求的覆盖面积,就是求被cover两次或者两次以上的长度 * 高的和
首先判断是否被cover过,先更新一下len
1.接着判断一下是否被cover过次或者两次以上,如果符合,直接等于右端点-左端点
2.如果不符合条件1,且l == r ,那么twice = 0
3.如果不符合2,但是满足cover == 1,那么twice[u] = len[u << 1] + len[u << 1 | 1], 因为左右区间被覆盖一次的长度会被再覆盖一次
4.如果不符合条件3,twice[u] = twice[u << 1] + twice[u << 1 | 1]
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const int N = 2010; const int M = 2010 << 2; struct Segment{ double l, r, h; int f; }S ; int cnt, n, m; int cover[M]; double pos , len[M], twice[M]; void build(int u, int l, int r) { len[u] = twice[u] = 0; cover[u] = 0; if (l == r) return ; int mid = (l + r) >> 1; build(u << 1, l, mid); build(u << 1 | 1, mid + 1, r); } int cmp(const Segment a, const Segment b) { return a.h < b.h; } void init() { scanf("%d", &n); double x1, y1, x2, y2; cnt = 1; for (int i = 1; i <= n; i++) { scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2); pos[cnt] = S[cnt].l = S[cnt + 1].l = x1; pos[cnt + 1] = S[cnt].r = S[cnt + 1].r = x2; S[cnt].h = y1; S[cnt + 1].h = y2; S[cnt].f = 1; S[cnt + 1].f = -1; cnt += 2; } sort(S + 1, S + cnt, cmp); sort(pos + 1, pos + cnt); m = 1; for (int i = 2; i < cnt; i++) if (pos[i] != pos[i - 1]) pos[++m] = pos[i]; build(1, 1, m); } void getlen(int u, int l, int r) { if (cover[u]) len[u] = pos[r + 1] - pos[l]; else if (l == r) len[u] = 0; else len[u] = len[u << 1] + len[u << 1 | 1]; if (cover[u] > 1) twice[u] = pos[r + 1] - pos[l]; else if (l == r) twice[u] = 0; else if (cover[u] == 1) twice[u] = len[u << 1] + len[u << 1 | 1]; else twice[u] = twice[u << 1] + twice[u << 1 | 1]; } void Modify(int u, int l, int r, int L, int R, int c) { if (l == L && r == R) { cover[u] += c; getlen(u, l, r); return ; } int mid = (l + r) >> 1; if (R <= mid) Modify(u << 1, l, mid, L, R, c); else if (L > mid) Modify(u << 1 | 1, mid + 1, r, L, R, c); else { Modify(u << 1, l, mid, L, mid, c); Modify(u << 1 | 1, mid + 1, r, mid + 1, R, c); } getlen(u, l, r); } int find(double val) { int l = 1, r = m; while (l <= r) { int mid = (l + r) >> 1; if (pos[mid] == val) return mid; else if (pos[mid] > val) r = mid - 1; else l = mid + 1; } return -1; } void solve() { double ans = 0; for (int i = 1; i < cnt; i++) { int l = find(S[i].l); int r = find(S[i].r) - 1; Modify(1, 1, m, l, r, S[i].f); ans += (S[i + 1].h - S[i].h) * twice[1]; } printf("%.2lf\n", ans); } int main() { int test; scanf("%d", &test); while (test--) { init(); solve(); } return 0; }
相关文章推荐
- csr 蓝牙
- JS中使用arguments.callee实现匿名函数的递归
- SQL*Plus 模拟 EBS环境
- 用Apache的commons-modeler来辅助开发JMX
- bash: mail: command not found的解决方法
- 解决ArcGIS局部刷新地图闪烁问题
- datepicker和datepickerdialog的实际应用区别
- 深入详解Struts2——struts.xml配置之Action配置详解
- 实现计步器中的判断运动状态功能
- 《程序员面试金典》--图中有向路径的检查
- [leetcode]#78 Subsets
- [MFC]CTreeView树形视图、CTreeCtrl树形控件
- jquery部分用法
- 链表基本操作
- BI ( 商务智能 ) 简介
- Ubuntu下HBase安装过程
- n人站圈报数,3 出列。 最后留下的人原来的位置 3种方式
- 网上数据格式化数据
- 优秀程序员的 18 大法则
- LNMP环境编译安装全过程(php-5.6.14、nginx-1.8.0、mysql-5.6.26)