hdu 4419 Colourful Rectangle (离散化扫描线线段树)
Problem - 4419
题意不难,红绿蓝三种颜色覆盖在平面上,不同颜色的区域相交会产生新的颜色,求每一种颜色的面积大小。
比较明显,这题要从矩形面积并的方向出发。如果做过矩形面积并的题,用线段树做的,这题就只差一个把每个区域计算单独出来的思路了。
这里不详细介绍扫描线,只是说一下针对这题的做法。其实网上有好多版本,都是直接单独计算答案的。然而,我稍微绕了个小弯,我觉得我这种处理方法也是比较容易想到以及实现的。如果我们用7棵线段树计算R、G、B、R||G、R||B、B||G、R||G||B这7种情况,我们并不能直接得到所要的答案。不过可以知道,ans(G)=S(R||G||B)-S(R||B)的(这里的||是两种颜色的面积并的意思)。同理我们可以得到ans(B)、ans(R)。然后根据这个,我们可以得到ans(RB)=S(R||G||B)-ans(R)-ans(B)-S(G)。同理可以得到ans(RG),ans(GB)。最后就只剩ans(RGB)了。
代码如下:
1 #include <cstdio> 2 #include <cstring> 3 #include <map> 4 #include <iostream> 5 #include <algorithm> 6 7 using namespace std; 8 9 map<char, int> id; 10 void preMap() { 11 id['R'] = 0; 12 id['G'] = 1; 13 id['B'] = 2; 14 } 15 16 const int N = 22222; 17 const int K = 1 << 3; 18 map<int, int> xid; 19 int rx[N], xn; 20 21 struct Node { 22 int id, x1, x2, y; 23 bool end; 24 Node() {} 25 Node(int id, int x1, int x2, int y, bool end) 26 : id(id), x1(x1), x2(x2), y(y), end(end) {} 27 } node[N]; 28 29 void input(int n) { 30 char buf[3]; 31 int a, b, c, d; 32 for (int i = 0; i < n; i++) { 33 scanf("%s%d%d%d%d", buf, &a, &b, &c, &d); 34 if (a > c) swap(a, c); 35 if (b > d) swap(b, d); 36 rx[i << 1] = a; 37 rx[i << 1 | 1] = c; 38 node[i << 1] = Node(id[buf[0]], a, c, b, false); 39 node[i << 1 | 1] = Node(id[buf[0]], a, c, d, true); 40 } 41 n <<= 1; 42 sort(rx, rx + n); 43 xn = unique(rx, rx + n) - rx; 44 // for (int i = 0; i < xn; i++) cout << rx[i] << ' '; cout << endl; 45 xid.clear(); 46 for (int i = 0; i < xn; i++) xid[rx[i]] = i; 47 for (int i = 0; i < n; i++) { 48 node[i].x1 = xid[node[i].x1]; 49 node[i].x2 = xid[node[i].x2]; 50 } 51 } 52 53 #define lson l, m, rt << 1 54 #define rson m + 1, r, rt << 1 | 1 55 #define root 0, xn - 1, 1 56 57 int sum[K][N << 2]; 58 int mk[K][N << 2]; 59 int cur; 60 61 void up(int rt, int l, int r) { 62 if (mk[cur][rt]) sum[cur][rt] = rx[r + 1] - rx[l]; 63 else sum[cur][rt] = sum[cur][rt << 1] + sum[cur][rt << 1 | 1]; 64 } 65 66 void build(int l, int r, int rt) { 67 sum[cur][rt] = mk[cur][rt] = 0; 68 if (l == r) return ; 69 int m = l + r >> 1; 70 build(lson); 71 build(rson); 72 } 73 74 void update(int k, int L, int R, int l, int r, int rt) { 75 if (L <= l && r <= R) { 76 mk[cur][rt] += k; 77 if (l != r) up(rt, l, r); 78 else { 79 if (mk[cur][rt]) sum[cur][rt] = rx[r + 1] - rx[l]; 80 else sum[cur][rt] = 0; 81 } 82 return ; 83 } 84 int m = l + r >> 1; 85 if (L <= m) update(k, L, R, lson); 86 if (m < R) update(k, L, R, rson); 87 up(rt, l, r); 88 } 89 90 bool cmp(Node a, Node b) { return a.y < b.y || a.y == b.y && a.end < b.end;} 91 92 typedef long long LL; 93 94 void work(int n) { 95 n <<= 1; 96 LL tt[K]; 97 memset(tt, 0, sizeof(tt)); 98 sort(node, node + n, cmp); 99 if (node[0].end) { puts("shit!!"); while (1) ;} 100 for (cur = 0; cur < K; cur++) { 101 build(root); 102 if (cur & 1 << node[0].id) update(1, node[0].x1, node[0].x2 - 1, root); 103 } 104 for (int i = 1; i < n; i++) { 105 for (cur = 0; cur < K; cur++) { 106 if (sum[cur][1] < 0 || sum[cur][1] > 1e9) { puts("shit!!!"); while (1) ;} 107 tt[cur] += (LL) sum[cur][1] * (node[i].y - node[i - 1].y); 108 if (cur & (1 << node[i].id)) update(node[i].end ? -1 : 1, node[i].x1, node[i].x2 - 1, root); 109 } 110 // for (int i = 0; i < K; i++) cout << tt[i] << ' '; cout << endl; 111 } 112 LL sgl[3], dbl[3], lst = tt[K - 1]; 113 for (int i = 0; i < 3; i++) { 114 sgl[i] = tt[K - 1] - tt[(K - 1) ^ (1 << i)]; 115 lst -= sgl[i]; 116 cout << sgl[i] << endl; 117 } 118 for (int i = 0; i < 3; i++) { 119 dbl[i] = tt[K - 1]; 120 for (int j = 0; j < 3; j++) { 121 if (i != j) dbl[i] -= sgl[j]; 122 else dbl[i] -= tt[1 << j]; 123 } 124 lst -= dbl[i]; 125 } 126 for (int i = 2; i >= 0; i--) cout << dbl[i] << endl; 127 cout << lst << endl; 128 } 129 130 int main() { 131 // freopen("in", "r", stdin); 132 preMap(); 133 int T, n; 134 scanf("%d", &T); 135 for (int cas = 1; cas <= T; cas++) { 136 scanf("%d", &n); 137 input(n); 138 printf("Case %d:\n", cas); 139 work(n); 140 } 141 return 0; 142 }
View Code
感觉这种方法写起来不会吃力,就是计算上面会稍微需要思考。不过我还是因为把xid写成xd导致wa了一个晚上。_(囧」∠)_
——written by Lyon
转载于:https://www.cnblogs.com/LyonLys/p/hdu_4419_Lyon.html
hdu 4419 Colourful Rectangle (离散化扫描线线段树)相关推荐
- POJ 1177 Picture [离散化+扫描线+线段树]
http://poj.org/problem?id=1177 给若干矩形,求被覆盖的区域的周长. 将 y 坐标离散化后,按 x 坐标进行扫描.用线段树维护两个东西,当前竖线的叠加长度 len 和 条数 ...
- HDU 1542:Atlantis(扫描线+线段树 矩形面积并)***
题目链接 题意 给出n个矩形,求面积并. 思路 使用扫描线,我这里离散化y轴,按照x坐标从左往右扫过去.离散化后的y轴可以用线段树维护整个y上面的线段总长度,当碰到扫描线的时候,就可以统计面积.这里要 ...
- HDU 1828:Picture(扫描线+线段树 矩形周长并)
题目链接 题意 给出n个矩形,求周长并. 思路 学了区间并,比较容易想到周长并. 我是对x方向和y方向分别做两次扫描线.应该记录一个pre变量,记录上一次扫描的时候的长度,对于每次遇到扫描线统计答案的 ...
- 【HDU5091】Beam Cannon,扫描线+线段树
传送门 思路: 扫描线的经典问题 然而并不是很会做-- 对x坐标差分一下(例如(x,y)类型为1,(x+w,y)的类型就是-1,以便于之后扫描可以去除该点),然后对y坐标转化为正数(便于操作为线段树上 ...
- 扫描线+线段树简介 AcWing 248窗内的星星题解
----出自南昌理工学院ACM集训队 这周学习了线段树和扫描线的解题方法,下面由小菜鸡简介一下: 一般扫描线的题目最简单的便是扫描线裸模板(一般来说的话:数据范围小),其次的话便是进行拓展成线段树+扫 ...
- POJ 1151 扫描线 线段树
题意:给定平面直角坐标系中的N个矩形,求它们的面积并. 题解:建立一个四元组(x,y1,y2,k).(假设y1<y2)用来储存每一条线,将每一条线按x坐标排序.记录所有的y坐标以后排序离散化.离 ...
- 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树
[BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...
- HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)
链接:线段树求矩形面积并 扫描线+离散化 1.给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 2.看完线段树求矩形面积并 的方法后,再看这题,求的是矩形面积交,类同. 求面积时,用被覆 ...
- [BZOJ4422][Cerc2015]Cow Confinement(扫描线+线段树)
=== === 这里放传送门 === === 题解 记得这题很久以前学长出过胡策..然后当时没做出来..然后照着题解打了一发然后怎么调怎么WA然后就弃了..当时的题解好像是用差分什么的?基本思路是对每 ...
最新文章
- 引用-ZIGBEE-ZSTACK网络配置相关问题
- 直线拟合的实现步骤和相关算子
- spring bean属性scope
- c++ 低位在前 高位在后_A股市场:如果股票涨停后第二天“高开低走”,你知道怎么操作才能利益最大化吗?...
- web下拉列表代码_文章列表总结(一)
- Flex 与.net 进行通信可以通过Fluorine(fluorinefx),WebORB For .net,Socket
- 企业常用的RPC框架比较
- 提升数据建模的10种技术措施
- 最通俗易懂的适配器模式
- qt传值给js及js传值给qt(qt及js的交互)
- 建设医疗人工智能的“四步曲”
- scrapy1.5文档(第二节 Scrapy Tutorial)
- winrar5.7.1商业版 无广告 注册下载
- Telink BDT 的使用方法
- js 验证身份证格式
- 分布式数据库原理解析
- 三跨复旦计算机 初复试经验贴
- linux 内核修改rss,什么是Linux内存管理中的RSS和VSZ
- Ubuntu19,新体验,无法识别移动硬盘以及硬盘修复
- 【机器学习实战】k-近邻算法案例——改进约会网站的配对效果
热门文章
- Newtonsoft.Json(Json.Net)学习笔记
- Ubuntu常用安装源
- VB API 之 第十一课 绘制矩形
- 搭建sql注入实验环境(基于windows)
- 一个简单的Ajax例子
- (转)百度文库浏览器分析及实现(续)
- 洛谷P4383 林克卡特树
- 初步认识深度学习笔记(一)
- AFNetworking 3.0 源码解读(十)之 UIActivityIndicatorView/UIRefreshControl/UIImageView + AFNetworking...
- Android 设置TextView字体加粗