题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积。

解法: 很容易想到线段树扫描线求矩形面积并,但是如何维护每种颜色的长度着实让我伤透了脑筋。后来看了一位朋友的题解,才幡然醒悟。

开始想到了用二进制表示颜色,R用001表示,G用010表示,B用100表示。那么就可以用十进制1~7表示7种不同颜色了。

维护 cov[rt][1~3] 表示此区间内3种原色各有多少个, Len[rt][i]表示每种颜色的长度。

重点是pushup的写法,详情见代码, 离散化什么还比较简单。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define lll __int64
using namespace std;
#define N 10107 lll Len[*N][];
int cov[*N][]; struct Line
{
int y1,y2,x;
int col;
}line[*N];
int yy[*N]; int cmp(Line ka,Line kb) { return ka.x < kb.x; } void pushup(int l,int r,int rt)
{
int state = ;
for(int i=;i<=;i++) if(cov[rt][i]) state |= (<<(i-)); //表示此区间内有的颜色
for(int i=;i<;i++) Len[rt][i] = ; //加了一层,要重新算各个颜色的长度
if(l+ == r) //叶子节点
{
Len[rt][state] = yy[r]-yy[l]; //只有此颜色state,长度为yy[r]-yy[l]
return;
}
for(int i=;i<;i++) //否则使用下面的更新
Len[rt][i|state] += Len[*rt][i] + Len[*rt+][i];
} void build(int l,int r,int rt)
{
for(int i=;i<=;i++) cov[rt][i] = ;
for(int i=;i<;i++) Len[rt][i] = ;
Len[rt][] = yy[r]-yy[l];
if(l == r-) return;
int mid = (l+r)/;
build(l,mid,*rt);
build(mid,r,*rt+);
} void update(int l,int r,int aa,int bb,int cover,int rt)
{
if(aa <= l && bb >= r)
{
if(cover > ) cov[rt][cover]++;
else cov[rt][-cover]--;
pushup(l,r,rt);
return;
}
if(l+ == r) return;
int mid = (l+r)/;
if(aa <= mid)
update(l,mid,aa,bb,cover,*rt);
if(bb > mid)
update(mid,r,aa,bb,cover,*rt+);
pushup(l,r,rt);
} int main()
{
int n,m,t,cs = ,i,j;
int x1,y1,x2,y2,c;
char ss[];
scanf("%d",&t);
while(t--)
{
m = ;
scanf("%d",&n);
for(i=;i<n;i++)
{
scanf("%s%d%d%d%d",ss,&x1,&y1,&x2,&y2);
if(ss[] == 'R') c = ;
else if(ss[] == 'G') c = ;
else c = ;
line[m].x = x1,line[m].y1 = y1,line[m].y2 = y2,line[m].col = c,yy[m++] = y1;
line[m].x = x2,line[m].y1 = y1,line[m].y2 = y2,line[m].col = -c,yy[m++] = y2;
}
m--;
sort(yy+,yy+m+);
int cnt = ;
for(i=;i<=m;i++)
{
if(yy[i] != yy[i-])
yy[cnt++] = yy[i];
}
cnt--;
build(,cnt,);
sort(line+,line+m+,cmp);
lll ans[];
memset(ans,,sizeof(ans));
printf("Case %d:\n",cs++);
for(i=;i<m;i++)
{
int L = lower_bound(yy+,yy+cnt+,line[i].y1)-yy;
int R = upper_bound(yy+,yy+cnt+,line[i].y2)-yy-;
update(,cnt,L,R,line[i].col,);
for(j=;j<;j++)
ans[j] += Len[][j]*(line[i+].x-line[i].x);
}
printf("%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n",ans[],ans[],ans[],ans[],ans[],ans[],ans[]);
}
return ;
}

HDU 4419 Colourful Rectangle --离散化+线段树扫描线的更多相关文章

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

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

  2. HDU 1264 Counting Squares (线段树-扫描线-矩形面积并)

    版权声明:欢迎关注我的博客.本文为博主[炒饭君]原创文章,未经博主同意不得转载 https://blog.csdn.net/a1061747415/article/details/25471349 P ...

  3. hdu 4419 Colourful Rectangle (离散化扫描线线段树)

    Problem - 4419 题意不难,红绿蓝三种颜色覆盖在平面上,不同颜色的区域相交会产生新的颜色,求每一种颜色的面积大小. 比较明显,这题要从矩形面积并的方向出发.如果做过矩形面积并的题,用线段树 ...

  4. HDU 1255 覆盖的面积 (线段树+扫描线+离散化)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 题意很清楚,就是让你求矩阵之间叠加层数大于1的矩形块的面积和. 因为n只有1000,所以我离散化 ...

  5. HDU 1542 矩形面积并【离散化+线段树+扫描线】

    <题目链接> 题目大意: 给你n个矩形,求出它们面积的并. 解题分析: 此题主要用到了扫描线的思想,现将各个矩形的横坐标离散化,然后用它们离散化后的横坐标(相当于将矩形的每条竖线投影在x轴 ...

  6. 【HDU4419 Colourful Rectangle】 线段树面积并

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4419 题目大意:给你n个矩形,每个矩形都有一种颜色,矩形覆盖会出现另外一种颜色,问你所有矩形中不同的颜 ...

  7. HDU1542-Atlantis【离散化&线段树&扫描线】个人认为很全面的详解

    刚上大一的时候见过这种题,感觉好牛逼哇,这都能算 如今已经不打了,不过适当写写题保持思维活跃度还是不错的,又碰到这种题了,想把它弄出来 说实话,智商不够,看了很多解析,花了4.5个小时才弄明白 网上好 ...

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

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

  9. HDU 3642 Get The Treasury (线段树扫描线,求体积并)

    参考链接 : http://blog.csdn.net/zxy_snow/article/details/6870127 题意:给你n个立方体,求覆盖三次以上(包括三次)的区域的体积 思路:先将z坐标 ...

随机推荐

  1. js实现向上滚动效果

    源码: <style type="text/css"> #up_zzjs{border:1px solid #ccc;width:170px;height:182px; ...

  2. jdbcTemplate queryForObject 查询 结果集 数量

    1.组织sql语句, 查询参数 数组, 设置返回类型 public int countByCondtion(String title, int mediaType, String currentSta ...

  3. ahjesus 创建msdn一样的帮助文档

    转载自http://www.cnblogs.com/DotNetNuke/archive/2009/04/23/1441899.html 使用SandCastle创建.Net帮助文档 Sandcast ...

  4. jsoup html采集器

    package com.forex.collect; import java.io.IOException;import java.util.HashMap;import java.util.Iter ...

  5. 写给java程序员的c++与java实现的一些重要细微差别

    0.其实常规的逻辑判断结构.工具类.文件读写.控制台读写这些的关系都不大,熟悉之后,这些都是灵活运用的问题. 学习c/c++需要预先知道的一个前提就是,虽然有ANSI C标准,但是每个c/c++编译器 ...

  6. Android Studio使用教程(一)(转)

    今年的Google全球开发者大会虽然没有新的Android系统和设备,但是还是推出了一些不错的产品,Android Studio就是其中之一.这个基于Intellij IDEA开发的Android I ...

  7. Oracle LPAD/RPAD函数在处理中文时的注意事项

    首先看下Oracle官方对函数的定义: The RPAD function returns an expression, right-padded to a specified length with ...

  8. 用win下的快捷键提高工作效率

    常用的快捷键: WIN+D:显示桌面,再按一次还原桌面: WIN+R:打开运行,输入命令可以执行相应操作,输入路径可以打开对应路径,输入程序名称可以打开对应程序(前提是你打开的是windows下面的程 ...

  9. android notification 传值关键

    android notification 传值关键在 onNewIntent方法里获取 @Override protected void onCreate(Bundle savedInstanceSt ...

  10. 关于android4.3 Intel X86 Atom System Image的下载

    今天建立android4.3模拟器的时候发现没有android4.3 Intel X86 Atom System Image可选,打开android SDK Manager 于是希望重现选择下载安装, ...