题意:给定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年杭州网络赛 扫描线+线段树的更多相关文章

  1. hdu 4046 2011北京赛区网络赛G 线段树 ***

    还带这么做的,卧槽,15分钟就被A了的题,居然没搞出来 若某位是1,则前两个为wb,这位就是w #include<cstdio> #include<cstring> #defi ...

  2. hdu 4027 2011上海赛区网络赛G 线段树 成段平方根 ***

    不能直接使用成段增减的那种,因为一段和的平方根不等于平方根的和,直接记录是否为1,是1就不需要更新了 #include<cstdio> #include<iostream> # ...

  3. HDU 5875 Function (2016年大连网络赛 H 线段树+gcd)

    很简单的一个题的,结果后台数据有误,自己又太傻卡了3个小时... 题意:给你一串数a再给你一些区间(lef,rig),求出a[lef]%a[lef+1]...%a[rig] 题解:我们可以发现数字a对 ...

  4. 19徐州网络赛E 线段树加离散化

    题目链接:https://nanti.jisuanke.com/t/41387 按wi的值建立权值线段树维护值为wi出现的最后位置,对于第i个人的答案,查询线段树[wi+m,max]区间的最大位置po ...

  5. 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 ...

  6. HDU 4738 Caocao's Bridges (2013杭州网络赛1001题,连通图,求桥)

    Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  7. HDU 4745 Two Rabbits (2013杭州网络赛1008,最长回文子串)

    Two Rabbits Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Tota ...

  8. HDU 4747 Mex (2013杭州网络赛1010题,线段树)

    Mex Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submis ...

  9. 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 ...

随机推荐

  1. 解决alaert.builder二次调用报错的bug

    报错的代码是: The specified child already has a parent. You must call removeView() on the child's parent f ...

  2. shell程序之逐行读取一文件里的參数且使用此參数每次运行5分钟

    /*********************************************************************  * Author  : Samson  * Date   ...

  3. Ewebeditor最新漏洞和漏洞指数

    Ewebeditor最新漏洞和漏洞指数[收集] 来源:转载作者:佚名时间:2009-06-03 00:04:26 下面文章收集转载于网络:) 算是比較全面的ewebeditor编辑器的漏洞收集,如今的 ...

  4. Source Insight 光标变粗设置NotePad++光标设置

    为了更好的查看文档和代码,避免半天都找不到光标的情况,故做此说明 Source Insight 光标变粗 菜单中 Options --->Preferences --->Typing -- ...

  5. 栈实现java

    栈是一种“先去后出”的抽象的数据结构.例如:我们在洗盘子的时候,洗完一个盘子,将其放在一摞盘子的最上面,但我们全部洗完后,要是有盘子时,我们会先从最上面的盘子开始使用,这种例子就像栈的数据结构一样,先 ...

  6. Swift新手教程3-字符串String

    原创blog,转载请注明出处 String 在swfit中,String兼容Unicode的方式.用法和C语言类似. 注意   在Cocoa和Cocoa touch中,Swift的String,和Fo ...

  7. 技术七Gitservergitolite要构建和操作方便

    最近,人懒,为了让自己的变化,所以,我决定花时间学习一些新的技术,.对于这些新技术,现在的需求不是很高.只需要在它的入口. 由于本人仅仅是花三四天整出来的东西,所以不洗勿喷,另外难免会有错误,如有还请 ...

  8. Git显示漂亮日志的小技巧

    Git的传统log如下所示,你喜欢吗? 看看下面这个你喜不喜欢?(点击图片看大图) 要做到这样,命令行如下: 1 git log --graph --pretty=format:'%Cred%h%Cr ...

  9. 从jdbc到mybatis

    前面我已经写了几篇文章介绍mybatis的使用方法, 现准备从原理上分析mybatis, 本篇将会解说JDBC演变到mybatis的过程. JDBC查询 使用jdbc查询数据库一般有下面七个步骤: 1 ...

  10. hdu 5091 Beam Cannon(扫描线段树)

    题目链接:hdu 5091 Beam Cannon 题目大意:给定N个点,如今要有一个W∗H的矩形,问说最多能圈住多少个点. 解题思路:线段的扫描线,如果有点(x,y),那么(x,y)~(x+W,y+ ...