-USACO 3.1Challenge: 染色矩形问题(rect1)
这道题有很多种做法
直接“灌水”很明显会TLE 直接不尝试、 略(可以用来对拍)
我用的是离散化+线段树
等于是有n个矩形,每个矩形有颜色,矩形覆盖+染色问题
首先把2n条平行于x轴的横线 离散化 (排序后保存在数组中)
那么同理,一共有2n条纵线,从左往右扫
对于每个矩形,左下角和右上角顶点坐标记为(x1,y1) (x2,y2)
则如果现在扫描到的纵线x=k满足x1<=k<x2则 线段树染色
比如有一种染色矩形(x1,y1) (x2,y2) 对应的是(1,2) (5,10)
现在扫描到的纵线横坐标为4 因为1<=4<5
所以需要对y1到y2这段区间染上新颜色
注意染色时由于后面的颜色会覆盖原来的颜色 应按顺序染色
注意染色 要用到lazy-tag思想 具体见http://www.cnblogs.com/Booble/archive/2010/10/09/1846911.html
计算就很简单了 如果这段区间col(记为颜色)>0 就增加这种颜色的面积 具体用hash表 哈希实现
主要还是离散化+线段树的基本操作(lazy-tag很重要,建议阅读上述博客 里面有移到pku2777 简单一维染色 、、这个等于是二维染色吧)
贴代码 (写得很囧) 可以简化的
最后一个数据1.2秒左右 也许这道题时限放宽了吧 线段树做法 应该都是这个复杂度、
{ ID: xiaweiy1 PROG: rect1 LANG: PASCAL } const maxn=40000; //2 maxn maxc=2500; type rec=record a,col:longint; end; trec=record l,r,col:longint; end; var a,b,n,i,sum,tmp,k:longint; sx,sy,ex,ey,paint,data,h:array[0..maxn]of longint; hash:array[1..maxc]of longint; ind:array[1..maxn+1]of rec; tree:array[1..maxn+1]of trec; procedure sorth(l,r: longint); var i,j,x,y: longint; begin i:=l; j:=r; x:=h[(l+r) div 2]; repeat while h[i]<x do inc(i); while x<h[j] do dec(j); if not(i>j) then begin y:=h[i]; h[i]:=h[j]; h[j]:=y; inc(i); j:=j-1; end; until i>j; if l<j then sorth(l,j); if i<r then sorth(i,r); end; procedure sortind(l,r: longint); var i,j,x1: longint; y:rec; begin i:=l; j:=r; x1:=ind[(l+r) div 2].a; repeat while (ind[i].a<x1) do inc(i); while (x1<ind[j].a) do dec(j); if not(i>j) then begin y:=ind[i]; ind[i]:=ind[j]; ind[j]:=y; inc(i); j:=j-1; end; until i>j; if l<j then sortind(l,j); if i<r then sortind(i,r); end; procedure lazytag(x:longint); begin if tree[x].col>0 then begin tree[x*2].col:=tree[x].col; tree[x*2+1].col:=tree[x].col; tree[x].col:=-1; end; end; procedure insert(x,f,t,c:longint); var mid:longint; begin if (f<=tree[x].l)and(tree[x].r<=t) then tree[x].col:=c else begin if tree[x].r-tree[x].l=1 then exit; lazytag(x); mid:=(tree[x].l+tree[x].r)div 2; if (f<mid) then insert(x*2,f,t,c); if (t>mid) then insert(x*2+1,f,t,c); end; end; procedure build(f,t,x:longint); var mid:longint; begin tree[x].l:=f; tree[x].r:=t; if (t-f<=1) then exit; mid:=(f+t)div 2; build(f,mid,x*2); build(mid,t,x*2+1); end; procedure count(x,width:longint); begin if tree[x].col>0 then begin hash[tree[x].col]:=hash[tree[x].col]+(h[tree[x].r]-h[tree[x].l])*width; end else begin if tree[x].r-tree[x].l>1 then begin count(x*2,width); count(x*2+1,width); end; end; end; function find(x:longint):longint; var le,ri,mid:longint; begin le:=1; ri:=2*n; while le<=ri do begin mid:=(le+ri)div 2; if h[mid]<x then le:=mid+1 else if h[mid]>x then ri:=mid-1 else begin exit(mid); end; end; end; begin assign(input,'rect1.in'); reset(input); assign(output,'rect1.out'); rewrite(output); readln(a,b,n); sx[1]:=0; sy[1]:=0; ex[1]:=a; ey[1]:=b; paint[1]:=1; inc(sum); h[sum]:=sy[1]; inc(sum); h[sum]:=ey[1]; for i:=1 to n do begin read(sx[i+1],sy[i+1],ex[i+1],ey[i+1],paint[i+1]); inc(sum); h[sum]:=sy[i+1]; inc(sum); h[sum]:=ey[i+1]; end; inc(n); sorth(1,2*n); for i:=1 to 2*n do begin if i mod 2=1 then data[i]:=find(sy[i div 2+1]) else data[i]:=find(ey[i div 2]); end; sum:=0; for i:=1 to n do begin inc(sum); ind[sum].a:=sx[i]; ind[sum].col:=paint[i]; inc(sum); ind[sum].a:=ex[i]; ind[sum].col:=paint[i]; // .a x1 (y1 y2) // .a x2 (y1 y2) end; sortind(1,sum); build(0,2*n,1); ind[sum+1].a:=ind[sum].a; for i:=1 to sum do begin for k:=1 to n do begin if (ind[i].a>=sx[k])and(ind[i].a<ex[k]) then insert(1,data[k*2-1],data[k*2],paint[k]); end; tmp:=ind[i+1].a-ind[i].a; count(1,tmp); end; for i:=1 to 2500 do begin if hash[i]<>0 then writeln(i,' ',hash[i]); end; close(input); close(output); end.
上一篇: 用Java实现的在线聊天项目中的SWT可视界面设计:好友列表窗口展示
下一篇: Java性能调优工具