//离散化 + 扫描线 + 线段树
//这个线段树跟平常不太一样的地方在于记录了区间两个信息,len[i]表示颜色为i的被覆盖的长度为len[i], num[i]表示颜色i 『完全』覆盖了该区间几层。len[i]起传递儿子与父亲的关系,而num[i]不起传递作用,只是单纯的表示被覆盖的区间。
//然后就是pushUp函数,必须在update到底层后即更新num[]和len,然后把len传上去。
//离散化后由于求的是面积,所以我是把每条长度为1的线段当做一个点, 即把左端点表示此段长度。而不是把点当成点。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath> using namespace std;
#define lson l, m, rt<<1
#define rson m + 1, r, rt<<1|1
typedef long long ll;
const int maxn = 2e4 + ; struct Seg{
char c;
int y, s, t, tag;
}ss[maxn];
bool cmp(Seg a, Seg b){
return a.y < b.y;
}
int san[maxn], tot;
int num[maxn << ][],len[maxn << ][];
ll ans[];
void pushUp(int l, int r, int rt){
int state = (num[rt][] > ? : ) | (num[rt][] > ? : ) | (num[rt][] > ? : );
memset(len[rt], , sizeof(len[rt]));
if (state){
len[rt][state] = san[r] - san[l - ];
for (int i = ; i < ; ++i){
if (state != (state|i)){
int tmp = len[rt<<][i] + len[rt<<|][i];
len[rt][state|i] += tmp;
len[rt][state] -= tmp;
}
}
}
else if (l != r){
for (int i = ; i < ; ++i) len[rt][i] = len[rt<<][i] + len[rt<<|][i];
}
}
int getC(char c){
if (c == 'R') return ;
if (c == 'G') return ;
return ;
}
void update(int L, int R, char c, int tag, int l, int r, int rt){
if (L <= l && R >= r){
int cc = getC(c);
num[rt][cc] += tag;
//注意
pushUp(l, r, rt);
return ;
}
int m = (l + r) >> ;
if (L <= m) update(L, R, c, tag, lson);
if (R > m) update(L, R, c, tag, rson);
pushUp(l, r, rt);
}
int T, n;
int main(){
int tcas = ;
int x1, x2, y1, y2;
char s[];
scanf("%d", &T);
while (T--){
scanf("%d", &n);
tot = ;
for (int i = ; i <= n; ++i){
scanf("%s%d%d%d%d", s,&x1, &y1, &x2, &y2);
ss[i].c = s[]; ss[i].y = y1; ss[i].s = x1; ss[i].t = x2, ss[i].tag= ;
ss[i + n].c = s[]; ss[i + n].y = y2; ss[i + n].s = x1; ss[i + n].t = x2, ss[i + n].tag = -;
san[tot++] = x1 ; san[tot++] = x2;
}
n = n * ; sort(san, san + tot);
tot = unique(san, san + tot) - san;
sort(ss + , ss + n + , cmp);
ss[].y = ss[].y; memset(num, , sizeof(num));
memset(len, , sizeof(len));
memset(ans, , sizeof(ans));
for (int i = ; i <= n; ++i){
int l = lower_bound(san, san + tot, ss[i].s) - san + ;
int r = lower_bound(san, san + tot, ss[i].t) - san;
/*cout << " l = " << l << " r = " << r ;
cout << " tag = " << ss[i].tag << " c = "<< ss[i].c << endl;
for (int j = 1; j < 8; ++j) cout << len[1][j] << " ";
cout << endl;
cout << endl;
*/
if (ss[i].y != ss[i - ].y){
for (int j = ; j < ; ++j){
ans[j] += (ll)(ss[i].y - ss[i - ].y) * (ll)len[][j];
}
}
update(l, r, ss[i].c, ss[i].tag, , tot - , );
}
printf("Case %d:\n", ++tcas);
swap(ans[], ans[]);
for (int i = ; i < ; ++i)
printf("%lld\n", ans[i]);
}
return ;
}

hdu 4419 线段树 扫描线 离散化 矩形面积的更多相关文章

  1. POJ-1151-Atlantis(线段树+扫描线+离散化)[矩形面积并]

    题意:求矩形面积并 分析:使用线段树+扫描线...因为坐标是浮点数的,因此还需要离散化! 把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用col表示该区间有多少个下边,sum代表该区 ...

  2. hdu1542 线段树扫描线求矩形面积的并

    题意:       给你n个正方形,求出他们的所占面积有多大,重叠的部分只能算一次. 思路:       自己的第一道线段树扫描线题目,至于扫描线,最近会写一个总结,现在就不直接在这里写了,说下我的方 ...

  3. HDU 1542 Atlantis(线段树扫描线+离散化求面积的并)

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  4. HDU 1542"Atlantis"(线段树+扫描线求矩形面积并)

    传送门 •题意 给你 n 矩形,每个矩形给出你 $(x_1,y_1),(x_2,y_2)$ 分别表示这个矩形的左下角和右上角坐标: 让你求这 n 个矩形并的面积: 其中 $x \leq 10^{5} ...

  5. hdu 1542&&poj 1151 Atlantis[线段树+扫描线求矩形面积的并]

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  6. HDU Atlantis 线段树 表达区间 矩形面积相交

    http://acm.hdu.edu.cn/showproblem.php?pid=1542 我的做法是把x轴的表示为线段,然后更新y 不考虑什么优化的话,开始的时候,把他们表达成线段,并按y排序,然 ...

  7. hdu 1255(线段树 扫描线) 覆盖的面积

    http://acm.hdu.edu.cn/showproblem.php?pid=1255 典型线段树辅助扫描线,顾名思义扫描线就是相当于yy出一条直线从左到右(也可以从上到下)扫描过去,此时先将所 ...

  8. 2015 UESTC 数据结构专题E题 秋实大哥与家 线段树扫描线求矩形面积交

    E - 秋实大哥与家 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/59 De ...

  9. hdu1828 线段树扫描线求矩形面积的周长

    题意:       给你n个矩形,问你这n个矩形所围成的图形的周长是多少. 思路:       线段树的扫描线简单应用,这个题目我用的方法比较笨,就是扫描两次,上下扫描,求出多边形的上下边长和,然后同 ...

随机推荐

  1. 我的mac OSX bash_profile文件

    A typical install of OS X won't create a .bash_profile for you. When you want to run functions from ...

  2. jquery如何判断checkbox(复选框)是否被选中 全选 反选

    好长时间没用jq, 之前用的都是ng. 想着随便参考一下,结果被坑.因为这篇文章是09年的,也和当时jq的版本号有关,但是为什么在百度排名第一,百度果然坑人,以后还是google 给出坑人文章的链接 ...

  3. 【微信转载】Google是如何做测试的

    就 目前的软件公司而言,Google无疑是在开放和创新力方面做得最好的.而如何支撑Google这种快速地扩张的研发能力以及迭代速度,并且产品质量总是 一如以往的能给人们很棒的用户体验?这是一个值得我们 ...

  4. 微信小程序 - 上传图片纯前端(多张、单张)

    演示如下 可能有些命名不太规范,到时改一下即可 点击从github拉取:图片上传示例

  5. eclipse工程重命名后,无法生产class问题

    在很多时候我们对project重新命名后,class文件始终没有生产,尤其是在web项目的时候,如果不注意class文件生成问题,会浪费大量的时间找错误.这里分享下如何解决eclipse重命名后cla ...

  6. Lomboz插件的介绍 下载 安装 问题

    http://www.blogjava.net/javaandcc/articles/251334.html Lomboz是Eclipse的一个主要的开源插件(open-source plug-in) ...

  7. EF中多表公共字段,以及设置EntityBase使所有实体类继承自定义类

    使用EF框架访问数据库时,如果某些表具有公共字段,例如在审核流程中,对于各类申请单资料的创建人.创建时间.修改人.修改时间,这些可能多表都需要的字段,如果在每个实体中进行赋值操作显然是类似和重复的,下 ...

  8. 使用Google Https搜索

    一. 将浏览器Google的默认搜索使用https 1. IE浏览器 进入注册表搜索"google.com"将搜索替换成https://www.google.com.hk 2. F ...

  9. 使用Linux环境变量教程

    什么是环境变量? bash shell用一个叫作环境变量( environment variable)的特性来存储有关shell会话和工作环境的信息(这也是它们被称作环境变量的原因).这项特性允许你在 ...

  10. Charles 的几个调试技巧

    Charles 是一个网络调试的代理工具,类似 Windows 下的 Fildder,这里介绍下几个常用的调试技巧,使用的版本是 Charles 4. 1.移动端抓包 在移动开发中,经常会遇到在手机上 ...