并查集(涂色问题) HDOJ 4056 Draw a Mess
题意:给出一个200 * 50000的像素点矩阵,执行50000次操作,每次把一个矩形/圆形/菱形/三角形内的像素点涂成指定颜色,问最后每种颜色的数量。
分析:乍一看,很像用线段树成段更新写,虽然复杂度有点大,但是也想不到其他的方法.这题可以巧妙地运用并查集来涂色.离线,从最后一个倒过来涂色,保证能涂上去的一定不会被覆盖,每次扫描一行,将一条线上的点都合并到右端点.
#include <bits/stdc++.h>
using namespace std; #define lson l, mid, o << 1
#define rson mid + 1, r, o << 1 | 1
typedef long long LL;
const int N = 5e4 + 2;
const int INF = 0x3f3f3f3f;
struct DSU {
int rt[N];
void clear(int n) {
fill (rt, rt+n, -1);
}
int Find(int x) {
return rt[x] == -1 ? x : rt[x] = Find (rt[x]);
}
void Union(int x, int y) {
rt[x] = y;
}
}dsu;
struct Point {
char str[20];
int xc, yc, a, b, c;
}p[N];
bool vis[N];
int ans[10];
int n, m, q; int squ(int x) {
return x * x;
} int cal(int x, int y) {
x = abs (x); y = abs (y);
return squ (x) + squ (y);
} int main(void) { //好题
while (scanf ("%d%d%d", &n, &m, &q) == 3) {
memset (ans, 0, sizeof (ans));
for (int i=0; i<q; ++i) {
scanf ("%s%d%d", &p[i].str, &p[i].xc, &p[i].yc);
if (p[i].str[0] == 'R') scanf ("%d%d%d", &p[i].a, &p[i].b, &p[i].c);
else scanf ("%d%d", &p[i].a, &p[i].c);
}
for (int i=0; i<n; ++i) {
dsu.clear (m); memset (vis, false, sizeof (vis));
for (int j=q-1; j>=0; --j) {
int left = 0, right = 0;
if (p[j].str[0] == 'C') {
if (squ (i - p[j].xc) > squ (p[j].a)) continue;
int tmp = (int) sqrt (1.0 * (squ (p[j].a) - squ (i - p[j].xc)));
left = p[j].yc - tmp; right = p[j].yc + tmp;
}
else if (p[j].str[0] == 'D') {
if (i < p[j].xc - p[j].a || i > p[j].xc + p[j].a) continue;
left = p[j].yc - p[j].a + abs (i - p[j].xc); right = p[j].yc + p[j].a - abs (i - p[j].xc);
}
else if (p[j].str[0] == 'R') {
if (i < p[j].xc || i > p[j].xc + p[j].a - 1) continue;
left = p[j].yc; right = p[j].yc + p[j].b - 1;
}
else if (p[j].str[0] == 'T') {
if (i < p[j].xc || i > p[j].xc + (p[j].a + 1) / 2 - 1) continue;
left = p[j].yc - p[j].a / 2 + (i - p[j].xc); right = p[j].yc + p[j].a / 2 - (i - p[j].xc);
}
if (left < 0) left = 0;
if (right >= m) right = m - 1;
int fa, fb = dsu.Find (right);
for (int k=left; k<=right; k=fa+1) { //paint a line
fa = dsu.Find (k);
if (!vis[fa]) {
ans[p[j].c]++; vis[fa] = true;
}
if (fa != fb) dsu.Union (fa, fb);
}
}
}
for (int i=1; i<=9; ++i) {
printf ("%d%c", ans[i], i == 9 ? '\n' : ' ');
}
} return 0;
}
并查集(涂色问题) HDOJ 4056 Draw a Mess的更多相关文章
- 转:并查集总结 例题:hdoj 1232 畅通工程
引述之类的就免了,我们现在做题碰到的并查集基础题目大都是连通城市(或者村庄学校),接下来我们就称每一个城市为一个元素.我们解决此类题目运用的是树结构,每个集合用一棵树表示,而树的节点用于存储集合中的元 ...
- 【HDOJ】4056 Draw a Mess
这题用线段树就MLE.思路是逆向思维,然后每染色一段就利用并查集将该段移除,均摊复杂度为O(n*m). /* 4056 */ #include <iostream> #include &l ...
- ZOJ 3544 / HDU 4056 Draw a Mess( 并查集好题 )
方法参见:http://blog.acmol.com/?p=751 从最后一个线段开始倒着处理(因为之后的线段不会被它之前的线段覆盖),把这条线段所覆盖的所有线段编号合并到一个集合里,并以最左边线段编 ...
- 【数轴涂色+并查集路径压缩+加速】C. String Reconstruction
http://codeforces.com/contest/828/problem/C [题意] [思路] 因为题目保证一定有解,所有优化时间复杂度的关键就是不要重复染色,所以我们可以用并查集维护区间 ...
- 并查集(HDOJ 1856)
并查集 英文:Disjoint Set,即“不相交集合” 将编号分别为1…N的N个对象划分为不相交集合, 在每个集合中,选择其中某个元素代表所在集合. 常见两种操作: n 合并两个集合 ...
- HDOJ并查集题目 HDOJ 1213 HDOJ 1242
Problem Description Today is Ignatius' birthday. He invites a lot of friends. Now it's dinner time. ...
- hdoj 1116 Play on Words 【并查集】+【欧拉路】
Play on Words Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) T ...
- 并查集 HDOJ 1232 畅通工程
题目传送门 /* 并查集(Union-Find)裸题 并查集三个函数:初始化Init,寻找根节点Find,连通Union 考察:连通边数问题 */ #include <cstdio> #i ...
- 并查集+树链剖分+线段树 HDOJ 5458 Stability(稳定性)
题目链接 题意: 有n个点m条边的无向图,有环还有重边,a到b的稳定性的定义是有多少条边,单独删去会使a和b不连通.有两种操作: 1. 删去a到b的一条边 2. 询问a到b的稳定性 思路: 首先删边考 ...
随机推荐
- September 4th 2016 Week 37th Sunday
The morning crowned the humble cloud with splendor. 晨光为谦逊的白云披上壮丽的光彩. Humility is a virtue. Many famo ...
- August 18th 2016 Week 34th Thursday
Comedy is acting out optimism. 喜剧就是将乐观演绎出来. Being optimistic or pessimistic, that is all about your ...
- java 资源监控
http://blog.csdn.net/huangzhaoyang2009/article/details/11860757 http://blog.csdn.net/cuker919/articl ...
- 6个原因说服你选择PostgreSQL9.6
PostgreSQL9.6在前些日子发布了, 社区为该版本的重大更新付诸良多, 发布日志一如既往的长,我挑选了6个重要的更新, 这些或许能够帮助你更好的使用PostgreSQL. 并行: 并行应该是这 ...
- sqlserver 用户、账号、安全等问题小汇
一.孤立账号 SQL Server 的用户安全管理分两层,整个SQL Server 服务器一层,每个数据库一层. 在服务器层的帐号,叫登录账户(SQL Server:服务器角色),可以设置它管理整个S ...
- Linux 通过os进程pid找到端口号
[root@xxxx conf]# netstat -lutpn|grep tcp /java tcp /java tcp /java tomcat 监听的一些端口
- WebService – 3.后台调用WebService,根级别上的数据无效
1.因为我的webservice返回的是json, 2.ajax传递跨域不安全, 3.contentType: "application/json; charset=utf-8", ...
- SQL分页存储过程——表名、返回的列、排序字段、排序类型、条件、页尺寸、页码
ALTER PROCEDURE [dbo].[SP_LGY_ICU_PAGECUT] ), -- 表名 ) = '*', -- 需要返回的列 )='''', -- 排序的欄位名 , -- 設置排序類型 ...
- php建立多层目录的函数
/** *根据路径path建立多级目录 *$dir目标目录 $mode权限,0700表示最高权限 */ function makedir( $dir , $mode = "0700" ...
- SQL语法中的JOIN类型
这个要弄明白哟..CROSS JOIN, NATURAL, INNER JOIN ,LEFT OUTER JOIN(LEFT JOIN) 等等....带LEFT,RIGHT的必为OUTER,所以OUT ...