【分段哈希】H. Paint the Wall

https://www.bnuoj.com/v3/contest_show.php?cid=9147#problem/H

【题意】

在一个长为H,宽为W的白墙上选一个矩形区域涂颜色,后涂的颜色会覆盖先涂的,题目给出n(n<=100)个矩形区域和对应的颜色。

求最后墙上每种颜色的面积是多少,共有多少种颜色。

【思路】

将墙分成一块一块的矩形区域,对每个区域判断最后涂的颜色是什么,将其面积加到对应的颜色上。关键是怎样将矩形分块:

将竖线(所有矩形的left和right)离散化,从左到右枚举相邻的竖线;

对固定的两条竖线,枚举覆盖这两条竖线的矩形,再离散化横线(所有合法矩形的top和bottom);

对当前的每个矩形区域,遍历所有的合法矩形,判断哪个是最后涂的。

时间复杂度是O(2n*2n*n)即O(n^3)。

【Accepted】

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<string>
  5 #include<cmath>
  6 #include<algorithm>
  7 
  8 using namespace std;
  9 int H,W;
 10 int n;
 11 const int maxn=4e2+5;
 12 int cnt;
 13 struct Rec
 14 {
 15     int T,L,B,R,c,o;
 16     void input(int o_)
 17     {
 18         o=o_;
 19         scanf("%d%d%d%d%d",&T,&L,&B,&R,&c);
 20     }
 21 }rec[maxn/2];
 22 int area[maxn];
 23 vector<int> v;
 24 int w[maxn];
 25 int h[maxn];
 26 void init()
 27 {
 28     cnt=0;
 29     memset(area,0,sizeof(area));
 30 }
 31 int main()
 32 {
 33     int cas=0;
 34     while(~scanf("%d%d",&H,&W))
 35     {
 36         if(!H&&!W)
 37         {
 38             break;
 39         }
 40         init();
 41         scanf("%d",&n);
 42         for(int i=1;i<=n;i++)
 43         {
 44             rec[i].input(i);
 45             w[++cnt]=rec[i].L;
 46             w[++cnt]=rec[i].R;    
 47         }
 48         getchar();
 49         sort(w+1,w+cnt+1);
 50         cnt=unique(w+1,w+cnt+1)-(w+1);
 51         for(int i=1;i<cnt;i++)
 52         {
 53             v.clear();
 54             int tot=0;
 55             for(int k=1;k<=n;k++)
 56             {
 57                 if(rec[k].L<=w[i]&&w[i+1]<=rec[k].R)
 58                 {
 59                     h[++tot]=rec[k].T;
 60                     h[++tot]=rec[k].B;
 61                     v.push_back(k);
 62                 }
 63             }
 64             sort(h+1,h+tot+1);
 65             tot=unique(h+1,h+tot+1)-(h+1);
 66             int sz=v.size();
 67             for(int k=1;k<tot;k++)
 68             {
 69                 int pos=-1;
 70                 for(int j=0;j<sz;j++)
 71                 {
 72                     if(rec[v[j]].T<=h[k]&&h[k+1]<=rec[v[j]].B)
 73                     {
 74                         if(pos<rec[v[j]].o)
 75                         {
 76                             pos=rec[v[j]].o;
 77                         }
 78                     }
 79                 }
 80                 if(pos!=-1)
 81                 {
 82                     area[rec[pos].c]+=(w[i+1]-w[i])*(h[k+1]-h[k]);
 83                 }
 84             }
 85         }
 86         if(cas)
 87         {
 88             puts("");
 89         }
 90         printf("Case %d:\n",++cas);
 91         int ans=0;
 92         for(int i=1;i<=100;i++)
 93         {
 94             if(area[i]>0)
 95             {
 96                 ans++;
 97                 printf("%d %d\n",i,area[i]);
 98             }
 99         }            
100         if(ans==1)
101         {
102             puts("There is 1 color left on the wall.");
103         }
104         else
105         {
106             printf("There are %d colors left on the wall.\n",ans);
107          } 
108     }
109     return 0;
110 }
View Code

 

posted @ 2017-07-04 19:42  shulin15  阅读(364)  评论(0编辑  收藏  举报