UVA1493 - Draw a Mess(并查集)

题目链接

题目大意:一个N * M 的矩阵,每次你在上面将某个范围上色,不论上面有什么颜色都会被最新的颜色覆盖,颜色是1-9,初始的颜色是0.最后输出这个矩形中。每一个颜色有多少个。某个范围这个分为了四种,圆,矩形,菱形,还有正三角形(倒着的)。注意这题的边界,不能超出这个矩形,非常easy越界。

解题思路:由于题的矩阵范围是200 * 50000,然后操作又是50000,这样三个相乘,即使给60s也是不够的。由于行的数目比較少。假设每次都能将这一行哪个没处理过直接拿出来。而不用一个一个推断就快非常多了,这样一来就相当于每一个格子仅仅要遍历一次。所以这里就每行用一个并查集。标记这这个位置以及后面的位置能够上色的起始位置。

然后颜色更新问题仅仅要将操作反着过来上色就能够处理了。

代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm> using namespace std;
const int M = 50005;
const int N = 205; int f[N][M];
int G[N][M];
int color[10];
int n, m, q;
char str[N]; struct OP { char type;
int x, y, l, r, c;
}op[M]; int getParent (int x, int y) {
return y == f[x][y] ? y : f[x][y] = getParent (x, f[x][y]);
} void init() { for (int i = q - 1; i >= 0; i--) { scanf ("%s", str);
if (str[0] == 'D')
scanf ("%d%d%d%d", &op[i].x, &op[i].y, &op[i].l, &op[i].c);
else if (str[0] == 'T')
scanf ("%d%d%d%d", &op[i].x, &op[i].y, &op[i].l, &op[i].c);
else if (str[0] == 'R')
scanf ("%d%d%d%d%d", &op[i].x, &op[i].y, &op[i].l, &op[i].r, &op[i].c);
else
scanf ("%d%d%d%d", &op[i].x, &op[i].y, &op[i].l, &op[i].c);
op[i].type = str[0];
} for (int i = 0; i <= n; i++)
for (int j = 0; j <= m; j++)
f[i][j] = j;
memset (color, 0, sizeof (color));
} void circle (int x, int y, int r, int c) { int L, R, s;
for (int i = -r; i <= r; i++) { s = sqrt(r * r - i * i);
if (i + x >= n || i + x < 0)
continue;
L = max(y - s, 0);
L = max (getParent (i + x, L), L);
R = min (s + y, m - 1); for (int j = L; j <= R; j++) {
if (j == getParent (i + x, j)) {
color[c]++;
f[i + x][j] = R + 1;
} else
j = getParent(i + x, j) - 1;
}
}
} void diamond (int x, int y, int r, int c) { int L, R;
for (int i = -r; i <= r; i++) { if (i + x >= n || i + x < 0)
continue;
R = min (r - abs(i) + y, m - 1);
L = max (abs(i) - r + y, 0);
L = max (L, getParent (i + x, L)); for (int j = L; j <= R; j++) {
if (j == getParent (i + x, j)) {
color[c]++;
f[i + x][j] = R + 1;
} else
j = getParent (i + x, j) - 1;
}
}
} void rectangle (int x, int y, int l, int w, int c) { int L, R;
for (int i = x; i < min(x + l, n); i++) { L = max (y, getParent (i, y));
R = min (y + w - 1, m - 1); for (int j = L; j <= R; j++) {
if (j == getParent (i, j)) {
color[c]++;
f[i][j] = R + 1;
} else
j = getParent (i, j) - 1;
}
}
} void triangle (int x, int y, int w, int c) { int L, R, h;
h = (w + 1) / 2;
for (int i = 0; i < h; i++) { if (i + x >= n)
break;
L = max (y - h + i + 1, 0);
L = max (getParent(i + x, L), L);
R = min (y + h - i - 1, m - 1); for (int j = L; j <= R; j++) {
if (j == getParent (i + x, j)) {
color[c]++;
f[i + x][j] = R + 1;
} else
j = getParent (i + x, j) - 1;
}
}
} void solve () { for (int i = 0; i < q; i++) { if (op[i].type == 'D')
diamond (op[i].x, op[i].y, op[i].l, op[i].c);
else if (op[i].type == 'C')
circle (op[i].x , op[i].y, op[i].l, op[i].c);
else if (op[i].type == 'T')
triangle (op[i].x, op[i].y, op[i].l, op[i].c);
else
rectangle (op[i].x, op[i].y, op[i].l, op[i].r, op[i].c);
}
} int main () { char str[N];
while (scanf ("%d%d%d", &n, &m, &q) != EOF) { init (); solve(); for (int i = 1; i < 9; i++)
printf ("%d ", color[i]);
printf ("%d\n", color[9]);
}
return 0;
}

UVA1493 - Draw a Mess(并查集)的更多相关文章

  1. uva 1493 - Draw a Mess(并查集)

    题目链接:uva 1493 - Draw a Mess 题目大意:给定一个矩形范围,有四种上色方式,后面上色回将前面的颜色覆盖,最后问9种颜色各占多少的区域. 解题思路:用并查集维护每一个位置相应下一 ...

  2. Draw a Mess (并查集)

    It's graduated season, every students should leave something on the wall, so....they draw a lot of g ...

  3. UVA 1493 Draw a Mess(并查集+set)

    这题我一直觉得使用了set这个大杀器就可以很快的过了,但是网上居然有更好的解法,orz... 题意:给你一个最大200行50000列的墙,初始化上面没有颜色,接着在上面可能涂四种类型的形状(填充):  ...

  4. 并查集(涂色问题) HDOJ 4056 Draw a Mess

    题目传送门 题意:给出一个200 * 50000的像素点矩阵,执行50000次操作,每次把一个矩形/圆形/菱形/三角形内的像素点涂成指定颜色,问最后每种颜色的数量. 分析:乍一看,很像用线段树成段更新 ...

  5. 【HDOJ】4056 Draw a Mess

    这题用线段树就MLE.思路是逆向思维,然后每染色一段就利用并查集将该段移除,均摊复杂度为O(n*m). /* 4056 */ #include <iostream> #include &l ...

  6. POJ 2912 - Rochambeau - [暴力枚举+带权并查集]

    题目链接:http://poj.org/problem?id=2912 Time Limit: 5000MS Memory Limit: 65536K Description N children a ...

  7. CodeForces Roads not only in Berland(并查集)

    H - Roads not only in Berland Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d ...

  8. POJ2912 Rochambeau [扩展域并查集]

    题目传送门 Rochambeau Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4463   Accepted: 1545 ...

  9. POJ2912:Rochambeau(带权并查集)

    Rochambeau Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5208   Accepted: 1778 题目链接:h ...

随机推荐

  1. UOJ#58/BZOJ 3052【WC2013】糖果公园

    好写好调的莫队算法,就算上树了仍然好写好调. 传送门 http://uoj.ac/problem/58 简要做法 将树按照dfs序分块,然后将询问按照(u所在块,v所在块,时间)作为关键字进行排序,依 ...

  2. ASP.NET中的状态保持

    1.ASP.NET中的状态保持解决方案 2.常用的状态报保持方式 view state  ASP.Net的.aspx页面特有,页面级的,就是在页面上的一个隐藏域中保存客户端单独使用的数据的一种方式(b ...

  3. PHP用imageTtfText函数在图片上写入汉字

    https://blog.csdn.net/smstong/article/details/43955705 PHP绘图,imageString()这个函数并不支持汉字的绘制.这往往会给入门者当头一棒 ...

  4. go语言入门(三)

    条件语句 go语言的条件语句结构如下: go语言的条件语句和其他语言类似.简单列举下: 1.if 语句,布尔表达式不需要括号 if 布尔表达式 { /* 在布尔表达式为 true 时执行 */ } 2 ...

  5. [ python ] 各种推导式

    各种推导式,主要使用示例演示用法 列表生成式 示例1:求0-9每个数的平方 li = [x*x for x in range(10)] print(li) # 执行结果: # [0, 1, 4, 9, ...

  6. beego学习笔记(4):开发文档阅读(6)

    beego的响应流程: 1.监听的端口接收数据,默认是8080端口. 2.用户请求到达8080端口后,开始数据处理流程. 3.初始化CONTEXT对象.判断是否是WEBSOCKET请求,如果是,设置I ...

  7. 总结开发ERP软件应遵循的一些基本原则

    总结一下做管理软件,有哪些项是经过检验的条款,必须遵守的. 界面篇 1  要保存用户的偏号(profile/favourite). ASP.NET 2.0引入此功能,当用户修改默认的控件的属性时,框架 ...

  8. java EE :Servlet 接口

    Servlet 生命周期  : 调用当前 Servlet 类构造函数进行实例化 Servlet 通过调用 init () 方法进行初始化 Servlet 调用 service() 方法来处理客户端的请 ...

  9. 使用CSS更改图标的颜色

    我们经常在很多网站上见到更改网站的主题时,图标的颜色也改变了,我们总是觉的这一项功能非常伟大,因为我们知道使用CSS是无法完成更改图片的颜色的.那么,网站上随心所欲的图标颜色是采用N多个图片不断的切换 ...

  10. BNUOJ 52505 Euclidean Geometry

    结论. 算了好久不会算,最后看了样例猜出了结论.次长边全用上,再用最长边减去次长边. #include<bits/stdc++.h> using namespace std; int T; ...