欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

-USACO 3.1Challenge: 染色矩形问题(rect1)

最编程 2024-07-30 07:30:42
...

这道题有很多种做法

直接“灌水”很明显会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.