hdu4419 Colourful Rectangle 12年杭州网络赛 扫描线+线段树
题意:给定n个矩形,每个矩形有一种颜色,RGB中的一种。相交的部分可能为RG,RB,GB,RGB,问这n个矩形覆盖的面积中,7种颜色的面积分别为多少
思路:把x轴离散化做扫描线,线段树维护一个扫描区间竖直方向上的各种颜色的长度
刚开始想着直接维护每段区间上7种颜色的长,但是写到删除的时候发现没办法删除,
然后想了半天,发现:需要的只是整个区间的颜色长度信息,所以,对于颜色更新来说,不需要往下传标记,只需要维护上push_up就好了
所以添加删除就简单多了。
用 1 2 4 分别代表R G B 然后RG RB GB RGB 分别为3 5 6 7
没有颜色用0来表示
线段树每个节点记录下R,G,B 分别被覆盖了几次。
往上更新的时候只需要考虑左右儿子的线段覆盖了父亲的颜色后总的区间各个颜色长度为多少即可,注意单个长度的情况。
一直卡在64位类型的转化上,全都换成64位的不对,最后强制转化才对的。。
// 略长,但是比较可看,
/// R:1 G:2 B:4
int hash[];
struct scanline
{
int x,y1,y2;
int col;
int flag ;
void set(int _x,int _y1,int _y2,int _col ,int _flag)
{
x = _x ;
y1 = _y1 ;
y2 = _y2 ;
col = _col ;
flag = _flag ;
}
};
bool cmp(scanline t1, scanline t2)
{
if(t1.x != t2.x)return t1.x < t2.x;
return t1.flag > t2.flag;
}
scanline sc[maxn * ];
int y[maxn * ];
int num;
struct node
{
int l,r;
int ml,mr;
int c1,c2,c4;
int l1[];
int mid()
{
return (l + r) /;
}
int len()
{
return mr - ml;
}
};
long long area[];
node tt[maxn * * ];
int nn ;
void init(int root )
{
memset(tt[root].l1,,sizeof(tt[root].l1));
tt[root].c1 = tt[root].c2 = tt[root].c4 = ;
}
void update1(int root )
{
// printf("root = %d\n",root);
int col = ;
if(tt[root].c1 > ) col = col|;
if(tt[root].c2 > ) col = col|;
if(tt[root].c4 > ) col = col|;
//printf("update1: col = %d\n",col);
memset(tt[root].l1,,sizeof(tt[root].l1));
if(tt[root].r - tt[root].l == )
{
tt[root].l1[col] = tt[root].len();
}
else if(col == )
{
for(int i = ;i < ;i ++ )
tt[root].l1[i] = tt[root*].l1[i] + tt[root*+].l1[i];
}
else if(col != )
{
for(int i = ; i < ; i ++ )
tt[root].l1[i|col] += (tt[root*].l1[i] + tt[root*+].l1[i]);
} return ;
}
void build(int root ,int l,int r )
{
tt[root].l = l ;
tt[root].r = r;
tt[root].ml = y[l-];
tt[root].mr = y[r-];
init(root);
tt[root].l1[] = tt[root].len();
if( l + >= r ) return ;
int mid = tt[root].mid();
build(root * , l , mid );
build(root * + , mid , r);
return ;
}
void upd(int root ,int l,int r ,int col,int val )
{
if(l <= tt[root].ml && tt[root].mr <= r)
{
if(col == ) tt[root].c1 += val ;
else if(col == ) tt[root].c2 += val ;
else if(col == ) tt[root].c4 += val ;
update1(root);
return ;
}
if(r <= tt[root * ].mr )
upd(root * , l,r,col,val);
else if(l >= tt[root * + ].ml )
upd(root * + , l,r ,col,val);
else
{
upd(root * ,l,r,col,val);
upd(root * + ,l,r,col,val);
}
update1(root);
}
int main()
{
int x1,x2,y1,y2;
memset(hash,,sizeof(hash));
hash['R'] = ;
hash['G'] = ;
hash['B'] = ;
int cas,ccc;
ccc = ;
char str[];
scanf("%d",&cas);
int n ;
while(cas -- )
{
num = ;
scanf("%d",&n);
for(int i = ; i <= n ; i++ )
{
scanf("%s %d %d %d %d",str,&x1,&y1,&x2,&y2);
y[num] = y1 ;
num ++ ;
sc[num].set(x1,y1,y2,hash[str[]],); y[num] = y2 ;
num ++ ;
sc[num].set(x2,y1,y2,hash[str[]],-);
}
int n1;
n1 = num ;
sort(y ,y + num);
nn = unique(y , y + num) - y;
build(,,nn);
sort(sc + , sc + n1 + ,cmp);
memset(area,,sizeof(area));
int i ;
i = ;
while(i <= n1 )
{
int j = i ;
while(sc[j].x == sc[i].x && j <= n1 )
{
upd(,sc[j].y1,sc[j].y2,sc[j].col,sc[j].flag);
j ++ ;
}
int len ;
if(j == n1 + ) len = ;
else len = sc[j].x - sc[i].x;
update1();
for(int k = ; k < ; k ++ )
area[k] = area[k] + (long long)(tt[].l1[k]) * (long long)(len) ;
i = j ;
}
printf("Case %d:\n",++ccc);
printf("%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n",area[],area[],area[],area[],area[],area[],area[]);
///cout<<area[1]<<endl<<area[2]<<endl<<area[4]<<endl<<area[3]<<endl<<area[5]<<endl<<area[6]<<endl<<area[7]<<endl;
}
return ;
}
hdu4419
hdu4419 Colourful Rectangle 12年杭州网络赛 扫描线+线段树的更多相关文章
- hdu 4046 2011北京赛区网络赛G 线段树 ***
还带这么做的,卧槽,15分钟就被A了的题,居然没搞出来 若某位是1,则前两个为wb,这位就是w #include<cstdio> #include<cstring> #defi ...
- hdu 4027 2011上海赛区网络赛G 线段树 成段平方根 ***
不能直接使用成段增减的那种,因为一段和的平方根不等于平方根的和,直接记录是否为1,是1就不需要更新了 #include<cstdio> #include<iostream> # ...
- HDU 5875 Function (2016年大连网络赛 H 线段树+gcd)
很简单的一个题的,结果后台数据有误,自己又太傻卡了3个小时... 题意:给你一串数a再给你一些区间(lef,rig),求出a[lef]%a[lef+1]...%a[rig] 题解:我们可以发现数字a对 ...
- 19徐州网络赛E 线段树加离散化
题目链接:https://nanti.jisuanke.com/t/41387 按wi的值建立权值线段树维护值为wi出现的最后位置,对于第i个人的答案,查询线段树[wi+m,max]区间的最大位置po ...
- HDU 4741 Save Labman No.004 (2013杭州网络赛1004题,求三维空间异面直线的距离及最近点)
Save Labman No.004 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- HDU 4738 Caocao's Bridges (2013杭州网络赛1001题,连通图,求桥)
Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- HDU 4745 Two Rabbits (2013杭州网络赛1008,最长回文子串)
Two Rabbits Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Tota ...
- HDU 4747 Mex (2013杭州网络赛1010题,线段树)
Mex Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submis ...
- HDU 4739 Zhuge Liang's Mines (2013杭州网络赛1002题)
Zhuge Liang's Mines Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
随机推荐
- 图的创建和遍历(BFS/DFS)
图的表示方法主要有邻接矩阵和邻接表.其中邻接表最为常用,因此这里便以邻接表为例介绍一下图的创建及遍历方法. 创建图用到的结构有两种:顶点及弧 struct ArcNode { int vertexIn ...
- [原创] linux 下上传 datapoint数据到yeelink 【golang版本】同时上传2个数据点
/* Create by sndnvaps<sndnvaps@gmail.com> * data: 2015-04-12* upload 2 datapoint to yeelink.ne ...
- Cocos2d-x学习笔记(19)(TestCpp源代码分析-3)
本章主要介绍testBasic.h/cpp,这两个文件主要用于返回主场景界面. //testBasic.h #ifndef _TEST_BASIC_H_ #define _TEST_BASIC_H_ ...
- Directx11学习笔记【二十】 使用DirectX Tool Kit加载mesh
本文由zhangbaochong原创,转载请注明出处:http://www.cnblogs.com/zhangbaochong/p/5788482.html 现在directx已经不再支持.x文件了, ...
- 原生javascript学习
首先在这里要非常感谢无私分享作品的网友们,这些代码片段主要由网友们平时分享的作品代码里面和经常去逛网站然后查看源文件收集到的.把平时网站上常用的一些实用功能代码片段通通收集起来,方便网友们学习使用,利 ...
- Android Java 与 C++ 恒调用,路径、文件名、延长的最大长度
/**************************************************************************** ********************* ...
- C#中的预编译指令介绍
原文:C#中的预编译指令介绍 1.#define和#undef 用法: #define DEBUG #undef DEBUG #define告诉编译器,我定义了一个DEBUG的一个符号,他类似一个变量 ...
- Everything中文绿色版在Win7/8/10用不了问题的图文教程,只显示盘符
打开Everything后点击菜单上的“工具”——“选项” 勾选 Everything Service 后,点应用 需要用到管理者权限
- 信息二战炸弹:中国到美国咨询公司Say no
疯抢/文 在禁止Windows8操作系统參与政府採购,以及在中国销售的全部外国IT产品和服务都须通过新的安全审查之后,英国<金融时报>今天报料中国已禁止国企使用美国咨询公司服务. 这则消息 ...
- 未能加载文件或程序集“Common”或它的某一个依赖项。试图加载格式不正确的程序
原因:操作系统是64位的,但发布的程序引用了一些32位的ddl,所以出现了兼容性的问题解决方案一:如果是64位机器,IIS——应用程序池——高级设置——启用32位应用程序 :true.解决方案二:修改 ...