Gym - 101550A(Artwork 倒序+并查集)
题目:

思路:
1、对输入数据离线,先把所有的黑线都画出来,统计一下剩余的白色连通块的个数,dfs过程将一个连通块放到一个集合中。
2、倒着往前消去黑线,如果当前的块A是白块就看他的四周有没有白块:有白块B,看A和B的祖先是不是一样,一样的话pass,否则合并连通块并且白色连通块的数目减一(当然第一个是跳过的)。四周全是黑块的话,白色连通块的数量加一。
3、用栈存储一下每一步的答案,最后输出就可以了。
PS:看错了q的数据范围,卡了三天,话说前两天答案状态是WA在test5,第三天就成了memor limit exceeded,然后就发现自己的错误了。菜是原罪啊!!
代码:
#include <bits/stdc++.h>
#define inf 1e9
#define FRE() freopen("in.txt","r",stdin)
using namespace std;
typedef long long ll;
const ll MOD = ;
const int maxn = 1e3+;
int mp[maxn][maxn],fa[maxn*maxn],vis[maxn][maxn];
int dir[][] = {{,},{-,},{,},{,-}};
struct label
{
int r1,c1;
int r2,c2;
} l[maxn*];
int r,c,q,num_white; int getId(int x,int y)
{
return x*c+y;
} void init()
{
num_white = ;
memset(mp,,sizeof(mp));
memset(vis,,sizeof(vis));
for(int i = ; i<maxn*maxn; i++)
{
fa[i] = i;
}
return;
} int Find(int x)
{
return fa[x]==x ? x : fa[x] = Find(fa[x]);
} void input()
{
int x1,x2,y1,y2;
for(int i = ; i<q; i++)
{
scanf("%d%d%d%d",&l[i].c1,&l[i].r1,&l[i].c2,&l[i].r2);
l[i].c1--,l[i].c2--,l[i].r1--,l[i].r2--;
if(l[i].r1==l[i].r2)
{
int x = l[i].r1;
for(int j = l[i].c1; j<=l[i].c2; j++)
mp[x][j]++;
}
else if(l[i].c1==l[i].c2)
{
int y = l[i].c2;
for(int j = l[i].r1; j<=l[i].r2; j++)
mp[j][y]++;
}
}
} bool inside(int x,int y)
{
if(x>= && x<r && y>= && y<c)
return true;
return false;
} void dfs(int x,int y,int iid)
{
int id = getId(x,y);
vis[x][y] = ;
fa[id] = iid;
for(int i = ; i<; i++)
{
int tx = x+dir[i][],ty = y+dir[i][];
if(inside(tx,ty) && !mp[tx][ty] && !vis[tx][ty])
{
dfs(tx,ty,iid);
}
}
return;
} bool _union(int x,int y)
{
int tx = Find(x),ty = Find(y);
if(tx!=ty)
{
fa[tx] = ty;
return true;
}
return false;
} void solve(int x,int y)
{
int f = ,isfirst = ;
for(int i = ; i<; i++)
{
int tx = x+dir[i][],ty = y+dir[i][];
if(inside(tx,ty))
{
if(!mp[tx][ty])
{
f = ;
if(_union(getId(x,y),getId(tx,ty)))
{
isfirst++;
if(isfirst == )
continue;
else
num_white--;
}
}
}
}
if(!f)
num_white++;
} void check()
{
for(int i = ; i<r; i++)
{
for(int j = ; j<c; j++)
{
printf("%d ",mp[i][j]);
}
printf("\n");
}
cout<<"GG"<<endl;
} void countWhite()
{
for(int i = ; i<r; i++)
{
for(int j = ; j<c; j++)
{
int id = getId(i,j);
if(!mp[i][j] && !vis[i][j])
{
dfs(i,j,id);
num_white++;
}
}
}
} int main()
{
//FRE();
scanf("%d%d%d",&c,&r,&q);
init();
input();
countWhite();
stack<int> ans;
for(int i = q-; i>=; i--)
{
ans.push(num_white);
int x1 = l[i].r1,x2=l[i].r2,y1=l[i].c1,y2=l[i].c2;
if(x1==x2)
{
for(int j=y1; j<=y2; j++)
{
mp[x1][j]--;
if(mp[x1][j]==)
{
solve(x1,j);
}
}
}
else if(y1==y2)
{
for(int j=x1; j<=x2; j++)
{
mp[j][y1]--;
if(mp[j][y1]==)
{
solve(j,y1);
}
}
}
//check();
}
while(!ans.empty())
{
printf("%d\n",ans.top());
ans.pop();
}
return ;
}
/*
4 6 5
2 2 2 6
1 3 4 3
2 5 3 5
4 6 4 6
1 6 4 6
*/
/*
1
3
3
4
3
*/
Gym - 101550A(Artwork 倒序+并查集)的更多相关文章
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) C 倒序并查集
C. Destroying Array time limit per test 1 second memory limit per test 256 megabytes input standard ...
- Gym - 101550A Artwork (并查集在线做法)
题目链接 题意:给你一个n*m的网格图,初始时格点全白,每次可以将一段连续的格点涂黑.求出每次操作之后白色连通块的数量. 看了看网上的题解,基本全是离线的做法.其实这道题是有在线的做法的,利用了对偶图 ...
- Gym 100814C Connecting Graph 并查集+LCA
Description standard input/output Statements Alex is known to be very clever, but Walter does not be ...
- Gym - 101243F Vitamins(思维+并查集)
题意 有三种药丸,白色W>红色R>蓝色B,给你m个约束条件,问你n个药丸的颜色,不能确定颜色输出‘?’ 题解 如果1<2<3,只要找到2就能确定1和3的颜色 如果2=4,只要确 ...
- 【BZOJ2054】疯狂的馒头(并查集)
/* 经典思路, 倒序并查集处理即可 */ #include<cstdio> #include<algorithm> #include<cstring> #incl ...
- 并查集【洛谷P1197】 [JSOI2008]星球大战
P1197 [JSOI2008]星球大战 题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系 ...
- Artwork Gym - 101550A 离线并查集
题目:题目链接 思路:每个空白区域当作一个并查集,因为正着使用并查集分割的话dfs会爆栈,判断过于复杂也会导致超时,我们采用离线反向操作,先全部涂好,然后把黑格子逐步涂白,我们把每个空白区域当作一个并 ...
- Codeforces Gym 100463E Spies 并查集
Spies Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100463/attachments Desc ...
- Gym - 100625G Getting Through 计算几何+并查集
http://codeforces.com/gym/100625/attachments/download/3213/2013-benelux-algorithm-programming-contes ...
随机推荐
- where 1=1影响效率以及having和where的区别
低效的“WHERE 1=1” 网上有不少人提出过类似的问题:“看到有人写了WHERE 1=1这样的SQL,到底是什么意 思?”. 其实使用这种用法的开发人员一般都是在使用动态组装的SQL. 让我们想像 ...
- 修改Android系统的触摸提示音【学习笔记】
平台信息:内核:Linux version 3.10.0系统:android/android6.0平台:rk3288 作者:庄泽彬(欢迎转载,请注明作者) 邮箱:2760715357@qq.com 本 ...
- PL/SQL -->隐式游标(SQL%FOUND)
PL/SQL -->隐式游标(SQL%FOUND) 分类: SQL/PLSQL 基础2010-12-22 16:23 4084人阅读 评论(0) 收藏 举报 sqlexceptionoracle ...
- HDU5834Magic boy Bi Luo with his excited tree 树形dp
分析:典型的两遍dfs树形dp,先统计到子树的,再统计从祖先来的,dp[i][0]代表从从子树回来的最大值,dp[i][1]代表不回来,id[i]记录从i开始到哪不回来 吐槽:赛场上想到了状态,但是不 ...
- 5 Application 对象
5.1鸟瞰Application对象 5.2 必须了解的面向显示特性 5.2.1 使用ScreenUpdating改进和完善执行性能 代码清单5.1:实现屏幕更新的性能 '代码清单5.1: 实现屏幕更 ...
- HDU2138 素数判定
HDU2138 给定N个32位大于等于2的正整数 输出其中素数的个数 用Miller Rabin 素数判定法 效率很高 数学证明比较复杂,略过, 会使用这个接口即可. #include<iost ...
- 昆石VOS3000_2.1.2.4完整安装包及安装脚本
安装包下载地址:http://www.51voip.org/post/56.html 安装教程: 上传安装包 ·给整个目录授权 chmod 777 /root/vosintsall `核实 关闭sel ...
- Linux C编程之一:Linux下c语言的开发环境
---恢复内容开始--- 今天开始根据Linux C编程相关视频的学习所做的笔记,希望能一直坚持下去... 1.开发环境的构成 编辑器:VI: 编译器:选择GNU C/C++编译器gcc: 调试器: ...
- Notepad++安装插件
https://sourceforge.net/projects/npp-plugins/files/ 下载完插件后,通过notepad++的设置>>>>导入>>& ...
- [Qt及Qt Quick开发实战精解] 第1章 多文档编辑器
这一章的例子是对<Qt Creator快速人门>基础应用篇各章节知识的综合应用, 也是一个规范的实例程序.之所以说其规范,是因为在这个程序中,我们对菜单什么时候可用/什么时候不可用.关 ...