hdu 4419 Colourful Rectangle (离散化扫描线线段树)
题意不难,红绿蓝三种颜色覆盖在平面上,不同颜色的区域相交会产生新的颜色,求每一种颜色的面积大小。
比较明显,这题要从矩形面积并的方向出发。如果做过矩形面积并的题,用线段树做的,这题就只差一个把每个区域计算单独出来的思路了。
这里不详细介绍扫描线,只是说一下针对这题的做法。其实网上有好多版本,都是直接单独计算答案的。然而,我稍微绕了个小弯,我觉得我这种处理方法也是比较容易想到以及实现的。如果我们用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 (离散化扫描线线段树)的更多相关文章
- HDU 4419 Colourful Rectangle --离散化+线段树扫描线
题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何 ...
- POJ_3470 Walls 【离散化+扫描线+线段树】
一.题面 POJ3470 二.分析 POJ感觉是真的老了. 这题需要一些预备知识:扫描线,离散化,线段树.线段树是解题的关键,因为这里充分利用了线段树区间修改的高效性,再加上一个单点查询. 为什么需要 ...
- HDU 1542:Atlantis(扫描线+线段树 矩形面积并)***
题目链接 题意 给出n个矩形,求面积并. 思路 使用扫描线,我这里离散化y轴,按照x坐标从左往右扫过去.离散化后的y轴可以用线段树维护整个y上面的线段总长度,当碰到扫描线的时候,就可以统计面积.这里要 ...
- HDU 4419 Colourful Rectangle(线段树+扫描线)
题目链接 主要是pushup的代码,其他和区间更新+扫描线差不多. 那个区间如果要再刷一层x,那么sum[x][rt] = que[r+1] - que[l];但是如果原本有颜色为i,颜色将会变成i| ...
- [HDU 4419] Colourful Rectangle (扫描线 矩形面积并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4419 题目大意:比矩形面积并多了颜色,问染成的每种颜色的面积. 矩形面积并的扫描线维护的是长度,这道题 ...
- poj 1151 Atlantis (离散化 + 扫描线 + 线段树 矩形面积并)
题目链接题意:给定n个矩形,求面积并,分别给矩形左上角的坐标和右上角的坐标. 分析: 映射到y轴,并且记录下每个的y坐标,并对y坐标进行离散. 然后按照x从左向右扫描. #include <io ...
- hdu 4419 Colourful Rectangle
http://acm.hdu.edu.cn/showproblem.php?pid=4419 题意:给出3种颜色,重叠会生成新的颜色,然后有一些矩形,求出每种颜色的面积. 转化为二进制表示颜色:001 ...
- HDU 1828:Picture(扫描线+线段树 矩形周长并)
题目链接 题意 给出n个矩形,求周长并. 思路 学了区间并,比较容易想到周长并. 我是对x方向和y方向分别做两次扫描线.应该记录一个pre变量,记录上一次扫描的时候的长度,对于每次遇到扫描线统计答案的 ...
- 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 ...
随机推荐
- 2019.9.24 csp-s模拟测试51(a) 反思总结
T1:还在头铁,顺便复习了一下lct[虽然这题用不上因为复杂度不对] 头铁结束. 虽然题目存在换根的操作,实际上并不用真的换根. 2操作中求lca的时候只要考虑原树上root和x.y的lca以及x,y ...
- JQ效果 透明图片覆盖动画
效果图呈上 先说思路 1,一个固定的框架,有两张图片,一张是狗狗的,一张是练习方式,想把做好的练习方式隐藏 2,效果上想要从下面滑动出来,所以透明框定位在下面 3,整理需要的东西,缓慢升起需要动画效果 ...
- ADSL pppoe 拔号工具rp-pppoe
rp-pppoe 目前在各大发行版本都是存在的,比如Redhat/Fedora.红旗.Slackware.Debian.SuSE等系统,都是采用这个拔号软件,所以您大可不必为下载源码编译安装.只需要在 ...
- Leetcode43. Multiply Strings字符串相乘(大数相乘)
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式. 示例 1: 输入: num1 = "2", num ...
- selenium(2):环境搭建完成后,初步运行遇到的问题
检验是否搭建成功. . 问题一:运行时候,报错:请停用以开发者模式运行的扩展程序 出现错误如下: 原因:chromedriver的版本号过低了. 解决办法:应该安装与chrome版本对应的chrome ...
- vuehomework1
红黄蓝三个按钮,点击不同的按钮可以切换一个200*200的矩形框对应的颜色 <!DOCTYPE html> <html lang="en"> <hea ...
- Sentinel 1.5.0 正式发布,引入 Reactive 支持
近日,流控降级组件 Sentinel 的又一个里程碑版本 1.5.0 正式发布. 该版本引入 Reactive 的支持,并提供多项新特性与改进.从 1.5.0 版本开始,Sentinel 仅支持 JD ...
- 【51NOD1028】大数乘法 V2
╰( ̄▽ ̄)╭ 给出2个大整数A,B,计算A*B的结果. (A,B的长度 <= 100000,A,B >= 0) (⊙ ▽ ⊙) 把大整数A看做一个次数界为lenA的多项式A(x),其中x ...
- 非接触型手掌静脉识别 PalmSecure™
静脉识别,使用近红外线读取静脉模式,与存储的静脉模式进行比较,进行本人识别的识别技术.富士通的PalmSecure™,利用该技术,由离开识别装置的位置,使用近红外线拍摄,与预先存储的静脉模式进行比较从 ...
- Java版阿里云通信短信发送API接口实例(新)
阿里云通信(原名阿里大于)的短信服务(Short Message Service)是阿里云为用户提供的一种通信服务的能力,支持快速发送短信验证码.短信通知等. 完美支撑双11期间2亿用户,发送6亿短信 ...