题目传送门

题意:给出一个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的更多相关文章

  1. 转:并查集总结 例题:hdoj 1232 畅通工程

    引述之类的就免了,我们现在做题碰到的并查集基础题目大都是连通城市(或者村庄学校),接下来我们就称每一个城市为一个元素.我们解决此类题目运用的是树结构,每个集合用一棵树表示,而树的节点用于存储集合中的元 ...

  2. 【HDOJ】4056 Draw a Mess

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

  3. ZOJ 3544 / HDU 4056 Draw a Mess( 并查集好题 )

    方法参见:http://blog.acmol.com/?p=751 从最后一个线段开始倒着处理(因为之后的线段不会被它之前的线段覆盖),把这条线段所覆盖的所有线段编号合并到一个集合里,并以最左边线段编 ...

  4. 【数轴涂色+并查集路径压缩+加速】C. String Reconstruction

    http://codeforces.com/contest/828/problem/C [题意] [思路] 因为题目保证一定有解,所有优化时间复杂度的关键就是不要重复染色,所以我们可以用并查集维护区间 ...

  5. 并查集(HDOJ 1856)

    并查集   英文:Disjoint Set,即“不相交集合” 将编号分别为1…N的N个对象划分为不相交集合, 在每个集合中,选择其中某个元素代表所在集合. 常见两种操作: n       合并两个集合 ...

  6. HDOJ并查集题目 HDOJ 1213 HDOJ 1242

    Problem Description Today is Ignatius' birthday. He invites a lot of friends. Now it's dinner time. ...

  7. hdoj 1116 Play on Words 【并查集】+【欧拉路】

    Play on Words Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) T ...

  8. 并查集 HDOJ 1232 畅通工程

    题目传送门 /* 并查集(Union-Find)裸题 并查集三个函数:初始化Init,寻找根节点Find,连通Union 考察:连通边数问题 */ #include <cstdio> #i ...

  9. 并查集+树链剖分+线段树 HDOJ 5458 Stability(稳定性)

    题目链接 题意: 有n个点m条边的无向图,有环还有重边,a到b的稳定性的定义是有多少条边,单独删去会使a和b不连通.有两种操作: 1. 删去a到b的一条边 2. 询问a到b的稳定性 思路: 首先删边考 ...

随机推荐

  1. Java抽象类接口、内部类题库

    一.    选择题 1. Person类和Test类的代码如下所示,则代码中的错误语句是(  C  ).(选择一项)   public class Person { public String nam ...

  2. Redis 数据持久化(一)

    Redis的模块化开发设计的还是相当不错的,在Bio.h和Bio.c文件中定义了一个多线程的文件任务处理模块,在添加和处理任务的时候使用互斥锁和条件变量进行的同步,而且本身也支持多线程,这个模块的支持 ...

  3. main方法并发测试

    public static void main(String[] args) throws Exception{ RequestModel r = new RequestModel(); r.setT ...

  4. MVC4 @RenderBody、@RenderSection、@RenderPage、Html.RenderPartial、Html.RenderAction的作用和区别

    1. RenderBody在Razor引擎中没有了“母版页”,取而代之的是叫做“布局”的页面(_Layout.cshtml)放在了共享视图文件夹中.在这个页面中,会看到标签里有这样一条语句:@Rend ...

  5. 字符匹配算法之Boyer-Moore算法

    Boyer-Moore算法的精华是从后向前,取好后缀与坏后缀中的最大移动位移动搜索词,以达到最快速检索的效果. 详情参考:http://www.ruanyifeng.com/blog/2013/05/ ...

  6. 关于Linux环境变量

    查看全局变量:  printenv 查看单个环境变量的值可以用echo命令,必须在环境变量的名称前放一个$符号 如:

  7. PHP数据库操作

    PHP实现数据库的增删改查 <?php $conn=mysql_connect('localhost','root','root'); if(!$conn){ echo "connec ...

  8. PHP 获取图像信息 getimagesize 函数

    getimagesize() 函数用于获取图像尺寸,类型等信息. imagesx() 函数用于获取图像的宽度. imagesy() 函数用于获取图像的高度. getimagesize() getima ...

  9. mxnet环境搭建随记

    安装mxnet还是遇到不少麻烦事,现在简单记一下,挖个坑,后续详细补充,打算写一下我的mxnet探索之旅. 更新: 具体安装mxnet,cuda,opencv过程已经补坑——点击进入 不知道为什么,在 ...

  10. Delphi函数的返回值(注意这里与C/C++等语言有差异)

    在C/C++等语言中,函数执行到 return 部分之后,将立即停止函数的执行,并返回值 但是在Delphi中不同 函数中,执行到result时,并不同于比如 C/C++ 中的 return,跳出函数 ...