前序:这题是2011年亚洲赛区的弱化版题目..原题(ZOJ 3544)是画三角形和圆形还有矩形
题意:
在一个屏幕上画q个带颜色的矩形
问9种颜色各占了几个格子
输入数据给出屏幕的长n(n <= 200) 宽m(m <= 50000) 和 q个矩形(q <= 50000)
接下来q行给出每个矩形的起始位置和长、宽以及矩形的颜色
最后输出9个颜色各占几个格子
思路:
先读入数据..
然后从最后一个矩形开始处理..
因为越后画的矩形肯定越靠前..即最后画的矩形肯定完全没有被覆盖..
然后我们把最后一个矩形覆盖的地方标记出来..
再处理倒数第2个矩形........................................
如果暴力处理肯定会超时..m太大了..
所以可以用并查集..
pre[x][y] = yy表示在x行..从y列到yy列都是被合并成一种颜色了的...
一开始所有的pre[x][y] = y表示当前行没有被合并..当对当前行y到某一行yy都涂上一个颜色的时候..就标记pre[x][y] = yy
这样下次遍历的时候如果发现pre[x][y] = yy;则从这一行开始到yy都可以不看..因为y~yy会被后来画的矩形给覆盖掉..
这样就节省了很多时间..
Tips:
应该把屏幕看成200个50000列
而不是50000个200行..否则遍历50000列的时候依然会超时..
P.S..我很不理解的是为什么我对行和列都用并查集来优化居然会超时..
这让我很不解..
附上tle代码..<这不科学..= =>
Code:
1 #include <stdio.h> 2 #include <cstring> 3 using namespace std; 4 5 int pre[210][50010]; 6 int find(int x, int y) 7 { 8 return pre[x][y] == y?y:(pre[x][y] = find(x, pre[x][y])); 9 } 10 11 struct Inf 12 { 13 int xc; 14 int yc; 15 int l; 16 int w; 17 int c; 18 }inf[50010]; 19 20 int cnt[10]; 21 int main() 22 { 23 int n, m, q; 24 while(EOF != scanf("%d %d %d", &n, &m, &q)) { 25 for(int i = 0; i <= n+1; ++i) 26 for(int j = 0; j <= m+1; ++j) 27 pre[i][j] = j; 28 for(int i = 0; i < 10; ++i) 29 cnt[i] = 0; 30 31 for(int i = 0; i < q; ++i) 32 scanf("%d %d %d %d %d", &inf[i].xc, &inf[i].yc, &inf[i].l, &inf[i].w, &inf[i].c); 33 34 for(int i = q-1; i >= 0; --i) { 35 for(int j = inf[i].xc; j <= inf[i].xc+inf[i].l-1; ++j) { 36 int fy = find(j, inf[i].yc+inf[i].w); 37 for(int k = inf[i].yc; k <= inf[i].yc+inf[i].w-1;) { 38 int fk = find(j, k); 39 if(fk != k) k = fk; 40 else { 41 cnt[inf[i].c]++; 42 pre[j][k] = fy; 43 k++; 44 } 45 } 46 } 47 } 48 49 for(int i = 1; i < 10; ++i) 50 printf("%d%c", cnt[i], i==9?'\n':' '); 51 } 52 return 0; 53 }
1 #include <stdio.h> 2 #include <cstring> 3 using namespace std; 4 5 struct Inf 6 { 7 int xc; 8 int yc; 9 int l; 10 int w; 11 int c; 12 }inf[50010]; 13 14 int prex[210][5010], prey[210][5010]; 15 int findx(int x, int y) 16 { 17 return prex[x][y] == x?x:(prex[x][y] = findx(prex[x][y], y)); 18 } 19 20 int findy(int x, int y) 21 { 22 return prey[x][y] == y?y:(prey[x][y] = findy(x, prey[x][y])); 23 } 24 25 26 int main() 27 { 28 int xc, yc, l, w, c; 29 int n, m, q; 30 int fy, fx, fj, fk; 31 int cnt[10]; 32 while(EOF != scanf("%d %d %d", &n, &m, &q)) { 33 for(int i = 0; i <= n+1; ++i) 34 for(int j = 0; j <= m+1; ++j) 35 prex[i][j] = i, prey[i][j] = j; 36 37 memset(cnt, 0, sizeof(cnt)); 38 39 for(int i = 0; i < q; ++i) 40 scanf("%d %d %d %d %d", &inf[i].xc, &inf[i].yc, &inf[i].l, &inf[i].w, &inf[i].c); 41 for(int i = q-1; i >= 0; --i) { 42 for(int j = inf[i].yc; j <= inf[i].yc+inf[i].w-1;) { 43 for(int k = inf[i].xc; k<= inf[i].xc+inf[i].l-1;) { 44 fy = findy(k, inf[i].yc+inf[i].w); 45 fj = findy(k, j); 46 if(j != fj) { 47 j = fj; 48 break; 49 } 50 else { 51 fx = findx(inf[i].xc+inf[i].l, j); 52 fk = findx(k, j); 53 if(k != fk) k = fk; 54 else { 55 k++; 56 cnt[inf[i].c] += 1; 57 prex[fk][fj] = fx; 58 } 59 } 60 prey[fk][fj] = fy; 61 } 62 if(j == fj) 63 j++; 64 } 65 } 66 67 for(int i = 1; i < 10; ++i) 68 printf("%d%c", cnt[i], i == 9?'\n':' '); 69 } 70 return 0; 71 }
扩展:一个简单的类似并查集应用..
Hlg 1041 http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1041
链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1619