zju1610 count the colors 线段树
2016-05-18 17:00
316 查看
题目大意
给n个线段,覆盖在一条直线上,每个线段都覆盖先前的线段(如果相重叠的话),每条线短都有自己的颜色,求最后有多少种颜色和每种颜色要多少段。
分析
就是例二和例三的结合。
首先定义cover如下:cover=-1表示该区间由多种颜色组成。cover>=0表示该区间只有一种单一的颜色cover。
然后,统计算法就要做一下大的改动:
递归定义改一改:function find(t:pnode;l,r:longint;var lo,ro:longint):longint;
Lo,ro表示当前子树的最左边的颜色和最右边的颜色。
使用一个数组Flag,初始化为0。统计线段树,对于找到的颜色c对Flag[c]加1。
如果当前子树的左子树的最右边的颜色(c)等于右子树的最左边的颜色(c),且不等于颜色0,那代表有两条相连的段是同一种颜色(c)组成的(是一段),那就把flag[c]减一(因为计算左右子树时多计算了一次)。
代码
给n个线段,覆盖在一条直线上,每个线段都覆盖先前的线段(如果相重叠的话),每条线短都有自己的颜色,求最后有多少种颜色和每种颜色要多少段。
分析
就是例二和例三的结合。
首先定义cover如下:cover=-1表示该区间由多种颜色组成。cover>=0表示该区间只有一种单一的颜色cover。
然后,统计算法就要做一下大的改动:
递归定义改一改:function find(t:pnode;l,r:longint;var lo,ro:longint):longint;
Lo,ro表示当前子树的最左边的颜色和最右边的颜色。
使用一个数组Flag,初始化为0。统计线段树,对于找到的颜色c对Flag[c]加1。
如果当前子树的左子树的最右边的颜色(c)等于右子树的最左边的颜色(c),且不等于颜色0,那代表有两条相连的段是同一种颜色(c)组成的(是一段),那就把flag[c]减一(因为计算左右子树时多计算了一次)。
代码
type pnode=^tnode; tnode=record lc,rc:pnode; c:longint; end; var t:pnode; i,j,k:longint; x,y:longint; n,m,nm:longint; f:array[-2..100000] of longint; procedure neww(var t:pnode); begin if t=nil then begin new(t); t^.c:=-2; t^.lc:=nil; t^.rc:=nil; end; end; procedure insert(var t:pnode; l,r,x,y,ce:longint); var i,j,k:longint; mid:longint; begin with t^ do begin if c<>ce then begin mid:=(l+r) div 2; if (l=x) and (r=y) then begin c:=ce; exit; end; if c<>-1 then begin neww(lc); neww(rc); lc^.c:=t^.c; rc^.c:=t^.c; t^.c:=-1; end; if (l<=x) and (mid>=y) then begin neww(lc); insert(lc,l,mid,x,y,ce); exit; end; if (mid<=x) and (r>=y) then begin neww(rc); insert(rc,mid,r,x,y,ce); exit; end; neww(lc); neww(rc); insert(lc,l,mid,x,mid,ce); insert(rc,mid,r,mid,y,ce); end; end; end; procedure find(t:pnode;l,r:longint;var lo,ro:longint); var mid,ans:longint; tl,tr:longint; begin if t=nil then exit; with t^ do begin mid:=(l+r) div 2; if c<>-1 then begin lo:=c; ro:=c; f[c]:=f[c]+1; exit; end; find(lc,l,mid,lo,tl); find(rc,mid,r,tr,ro); if (tl=tr) and (tl<>-2) then begin ans:=ans-1; f[tl]:=f[tl]-1; end; end; end; begin while not eof do begin readln(n); m:=8000; fillchar(t,sizeof(t),0); fillchar(f,sizeof(f),0); neww(t); nm:=0; for i:=1 to n do begin readln(x,y,j); insert(t,0,m,x,y,j); if j>nm then nm:=j; end; i:=0; j:=0; find(t,0,m,i,j); for i:=0 to nm do if f[i]<>0 then writeln(i,' ',f[i]); writeln; end; end.
相关文章推荐
- 计算机视觉--常用数据库网址
- android studio 快捷键及使用方法,快速掌握
- 新数字三角形问题
- C语言实现ping功能(查看设备联网状态)
- SpringMVC 文件上传配置,多文件上传,使用的MultipartFile(转)
- 柴俊理金:美指疯涨黄金回落,原油震荡冲高在即
- html5-在网页中来回拖放图片
- 控制反转和依赖注入
- 动态加载so文件
- iOS APP删除系统相册中选中的图片
- Win10怎么调节虚拟内存大小? Win10虚拟内存调整的技巧
- 移动端SDK的优化之路
- 排序算法——基数排序
- js try{}catch(err){} 异常处理
- 【bzoj2115】[Wc2011] Xor 线性代数
- Junit参数化设置
- 安卓菜鸟开发笔记(10-7)图片颜色变化
- redis命中率计算
- BZOJ4436 [Cerc2015]Kernel Knights
- 504 Gateway time-out