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)了。

代码如下:

 #include <cstdio>
#include <cstring>
#include <map>
#include <iostream>
#include <algorithm> using namespace std; map<char, int> id;
void preMap() {
id['R'] = ;
id['G'] = ;
id['B'] = ;
} const int N = ;
const int K = << ;
map<int, int> xid;
int rx[N], xn; struct Node {
int id, x1, x2, y;
bool end;
Node() {}
Node(int id, int x1, int x2, int y, bool end)
: id(id), x1(x1), x2(x2), y(y), end(end) {}
} node[N]; void input(int n) {
char buf[];
int a, b, c, d;
for (int i = ; i < n; i++) {
scanf("%s%d%d%d%d", buf, &a, &b, &c, &d);
if (a > c) swap(a, c);
if (b > d) swap(b, d);
rx[i << ] = a;
rx[i << | ] = c;
node[i << ] = Node(id[buf[]], a, c, b, false);
node[i << | ] = Node(id[buf[]], a, c, d, true);
}
n <<= ;
sort(rx, rx + n);
xn = unique(rx, rx + n) - rx;
// for (int i = 0; i < xn; i++) cout << rx[i] << ' '; cout << endl;
xid.clear();
for (int i = ; i < xn; i++) xid[rx[i]] = i;
for (int i = ; i < n; i++) {
node[i].x1 = xid[node[i].x1];
node[i].x2 = xid[node[i].x2];
}
} #define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define root 0, xn - 1, 1 int sum[K][N << ];
int mk[K][N << ];
int cur; void up(int rt, int l, int r) {
if (mk[cur][rt]) sum[cur][rt] = rx[r + ] - rx[l];
else sum[cur][rt] = sum[cur][rt << ] + sum[cur][rt << | ];
} void build(int l, int r, int rt) {
sum[cur][rt] = mk[cur][rt] = ;
if (l == r) return ;
int m = l + r >> ;
build(lson);
build(rson);
} void update(int k, int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
mk[cur][rt] += k;
if (l != r) up(rt, l, r);
else {
if (mk[cur][rt]) sum[cur][rt] = rx[r + ] - rx[l];
else sum[cur][rt] = ;
}
return ;
}
int m = l + r >> ;
if (L <= m) update(k, L, R, lson);
if (m < R) update(k, L, R, rson);
up(rt, l, r);
} bool cmp(Node a, Node b) { return a.y < b.y || a.y == b.y && a.end < b.end;} typedef long long LL; void work(int n) {
n <<= ;
LL tt[K];
memset(tt, , sizeof(tt));
sort(node, node + n, cmp);
if (node[].end) { puts("shit!!"); while () ;}
for (cur = ; cur < K; cur++) {
build(root);
if (cur & << node[].id) update(, node[].x1, node[].x2 - , root);
}
for (int i = ; i < n; i++) {
for (cur = ; cur < K; cur++) {
if (sum[cur][] < || sum[cur][] > 1e9) { puts("shit!!!"); while () ;}
tt[cur] += (LL) sum[cur][] * (node[i].y - node[i - ].y);
if (cur & ( << node[i].id)) update(node[i].end ? - : , node[i].x1, node[i].x2 - , root);
}
// for (int i = 0; i < K; i++) cout << tt[i] << ' '; cout << endl;
}
LL sgl[], dbl[], lst = tt[K - ];
for (int i = ; i < ; i++) {
sgl[i] = tt[K - ] - tt[(K - ) ^ ( << i)];
lst -= sgl[i];
cout << sgl[i] << endl;
}
for (int i = ; i < ; i++) {
dbl[i] = tt[K - ];
for (int j = ; j < ; j++) {
if (i != j) dbl[i] -= sgl[j];
else dbl[i] -= tt[ << j];
}
lst -= dbl[i];
}
for (int i = ; i >= ; i--) cout << dbl[i] << endl;
cout << lst << endl;
} int main() {
// freopen("in", "r", stdin);
preMap();
int T, n;
scanf("%d", &T);
for (int cas = ; cas <= T; cas++) {
scanf("%d", &n);
input(n);
printf("Case %d:\n", cas);
work(n);
}
return ;
}

  感觉这种方法写起来不会吃力,就是计算上面会稍微需要思考。不过我还是因为把xid写成xd导致wa了一个晚上。_(囧」∠)_

——written by Lyon

hdu 4419 Colourful Rectangle (离散化扫描线线段树)的更多相关文章

  1. HDU 4419 Colourful Rectangle --离散化+线段树扫描线

    题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何 ...

  2. POJ_3470 Walls 【离散化+扫描线+线段树】

    一.题面 POJ3470 二.分析 POJ感觉是真的老了. 这题需要一些预备知识:扫描线,离散化,线段树.线段树是解题的关键,因为这里充分利用了线段树区间修改的高效性,再加上一个单点查询. 为什么需要 ...

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

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

  4. HDU 4419 Colourful Rectangle(线段树+扫描线)

    题目链接 主要是pushup的代码,其他和区间更新+扫描线差不多. 那个区间如果要再刷一层x,那么sum[x][rt] = que[r+1] - que[l];但是如果原本有颜色为i,颜色将会变成i| ...

  5. [HDU 4419] Colourful Rectangle (扫描线 矩形面积并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4419 题目大意:比矩形面积并多了颜色,问染成的每种颜色的面积. 矩形面积并的扫描线维护的是长度,这道题 ...

  6. poj 1151 Atlantis (离散化 + 扫描线 + 线段树 矩形面积并)

    题目链接题意:给定n个矩形,求面积并,分别给矩形左上角的坐标和右上角的坐标. 分析: 映射到y轴,并且记录下每个的y坐标,并对y坐标进行离散. 然后按照x从左向右扫描. #include <io ...

  7. hdu 4419 Colourful Rectangle

    http://acm.hdu.edu.cn/showproblem.php?pid=4419 题意:给出3种颜色,重叠会生成新的颜色,然后有一些矩形,求出每种颜色的面积. 转化为二进制表示颜色:001 ...

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

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

  9. HDU 3265/POJ 3832 Posters(扫描线+线段树)(2009 Asia Ningbo Regional)

    Description Ted has a new house with a huge window. In this big summer, Ted decides to decorate the ...

随机推荐

  1. Leetcode34.Find First and Last Position of Element in Sorted Array在排序数组中查找元素的位置

    给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂度必须是 O(log n) 级别. 如果数组中不存在目标值,返回 [ ...

  2. Ubuntu下安装Mongo方法

    场景:Ubuntu14下安装mongo,建议不要使用apt-get install 的命令安装,因为版本比较老 1.deb下载地址(可以自行选择OS,版本,server或tool或shell)http ...

  3. 使用SQLyog将Mysql中的表导出为Excel

    有时会有这样的需求:将MYSQL数据库中的某个表格导出,存为Excel文件.下面介绍步骤: 1.打开SQLyog,选中要导出的表 2.右键--备份/导出--导出表数据作为... 3.如图选择 Exce ...

  4. JavaScript--放大镜

    上例图: <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF- ...

  5. SDUT-2144_最小生成树

    数据结构实验之图论九:最小生成树 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 有n个城市,其中有些城市之间可以修建公 ...

  6. 如何在Liferay 7中创建一个简单的JSF Portlet

    这个将在Liferay IDE 3.1 M3的发布版中提供创建的选项,但是你也可以通过命令行来创建. 1.这是Liferay JSF团队的官网:http://liferayfaces.org/ 你能在 ...

  7. celery 动态定时任务探索

    环境: celery 4.3 flask python 3.7 linux 需求: 动态添加定时任务,且方便维护. 解决思路: 参考django-celery 或是celery源码,将定时任务配置放置 ...

  8. hdu5441 并查集 长春网赛

    对于每次询问的大的值,都是从小的值开始的,那就从小到大处理,省去很多时间,并且秩序遍历一遍m; 这题cin容易超时,scanf明显快很多很多.G++又比C++快; //这代码scanf400+,cin ...

  9. Windows 配置 Aria2 及 Web 管理面板教程

    今天闲来没事,想找点东西折腾下,然后看到个在 Debian 7 x64 系统环境下配置 Aria2 和 Web 管理面板的教程,针对 Linux 服务器用的.但很多人没服务器,也不知道什么是 Aria ...

  10. sqlite数据库文件导入到sqlserver 2016-03-26 21:55 1292人阅读 评论(1) 收藏

    最近在公司做项目,需要做两个版本,都是cs的,然后要求是一个单机版,自带数据库,另一个要进行局域网内的连接,所以公司的大牛设计是,局域网版的用sqlserver2008,单机版的则用sqlite.然后 ...