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 (离散化扫描线线段树)相关推荐

  1. POJ 1177 Picture [离散化+扫描线+线段树]

    http://poj.org/problem?id=1177 给若干矩形,求被覆盖的区域的周长. 将 y 坐标离散化后,按 x 坐标进行扫描.用线段树维护两个东西,当前竖线的叠加长度 len 和 条数 ...

  2. HDU 1542:Atlantis(扫描线+线段树 矩形面积并)***

    题目链接 题意 给出n个矩形,求面积并. 思路 使用扫描线,我这里离散化y轴,按照x坐标从左往右扫过去.离散化后的y轴可以用线段树维护整个y上面的线段总长度,当碰到扫描线的时候,就可以统计面积.这里要 ...

  3. HDU 1828:Picture(扫描线+线段树 矩形周长并)

    题目链接 题意 给出n个矩形,求周长并. 思路 学了区间并,比较容易想到周长并. 我是对x方向和y方向分别做两次扫描线.应该记录一个pre变量,记录上一次扫描的时候的长度,对于每次遇到扫描线统计答案的 ...

  4. 【HDU5091】Beam Cannon,扫描线+线段树

    传送门 思路: 扫描线的经典问题 然而并不是很会做-- 对x坐标差分一下(例如(x,y)类型为1,(x+w,y)的类型就是-1,以便于之后扫描可以去除该点),然后对y坐标转化为正数(便于操作为线段树上 ...

  5. 扫描线+线段树简介 AcWing 248窗内的星星题解

    ----出自南昌理工学院ACM集训队 这周学习了线段树和扫描线的解题方法,下面由小菜鸡简介一下: 一般扫描线的题目最简单的便是扫描线裸模板(一般来说的话:数据范围小),其次的话便是进行拓展成线段树+扫 ...

  6. POJ 1151 扫描线 线段树

    题意:给定平面直角坐标系中的N个矩形,求它们的面积并. 题解:建立一个四元组(x,y1,y2,k).(假设y1<y2)用来储存每一条线,将每一条线按x坐标排序.记录所有的y坐标以后排序离散化.离 ...

  7. 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树

    [BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...

  8. HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)

    链接:线段树求矩形面积并 扫描线+离散化 1.给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 2.看完线段树求矩形面积并 的方法后,再看这题,求的是矩形面积交,类同. 求面积时,用被覆 ...

  9. [BZOJ4422][Cerc2015]Cow Confinement(扫描线+线段树)

    === === 这里放传送门 === === 题解 记得这题很久以前学长出过胡策..然后当时没做出来..然后照着题解打了一发然后怎么调怎么WA然后就弃了..当时的题解好像是用差分什么的?基本思路是对每 ...

最新文章

  1. 引用-ZIGBEE-ZSTACK网络配置相关问题
  2. 直线拟合的实现步骤和相关算子
  3. spring bean属性scope
  4. c++ 低位在前 高位在后_A股市场:如果股票涨停后第二天“高开低走”,你知道怎么操作才能利益最大化吗?...
  5. web下拉列表代码_文章列表总结(一)
  6. Flex 与.net 进行通信可以通过Fluorine(fluorinefx),WebORB For .net,Socket
  7. 企业常用的RPC框架比较
  8. 提升数据建模的10种技术措施
  9. 最通俗易懂的适配器模式
  10. qt传值给js及js传值给qt(qt及js的交互)
  11. 建设医疗人工智能的“四步曲”
  12. scrapy1.5文档(第二节 Scrapy Tutorial)
  13. winrar5.7.1商业版 无广告 注册下载
  14. Telink BDT 的使用方法
  15. js 验证身份证格式
  16. 分布式数据库原理解析
  17. 三跨复旦计算机 初复试经验贴
  18. linux 内核修改rss,什么是Linux内存管理中的RSS和VSZ
  19. Ubuntu19,新体验,无法识别移动硬盘以及硬盘修复
  20. 【机器学习实战】k-近邻算法案例——改进约会网站的配对效果

热门文章

  1. Newtonsoft.Json(Json.Net)学习笔记
  2. Ubuntu常用安装源
  3. VB API 之 第十一课 绘制矩形
  4. 搭建sql注入实验环境(基于windows)
  5. 一个简单的Ajax例子
  6. (转)百度文库浏览器分析及实现(续)
  7. 洛谷P4383 林克卡特树
  8. 初步认识深度学习笔记(一)
  9. AFNetworking 3.0 源码解读(十)之 UIActivityIndicatorView/UIRefreshControl/UIImageView + AFNetworking...
  10. Android 设置TextView字体加粗