题目:

思路:

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 倒序+并查集)的更多相关文章

  1. 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 ...

  2. Gym - 101550A Artwork (并查集在线做法)

    题目链接 题意:给你一个n*m的网格图,初始时格点全白,每次可以将一段连续的格点涂黑.求出每次操作之后白色连通块的数量. 看了看网上的题解,基本全是离线的做法.其实这道题是有在线的做法的,利用了对偶图 ...

  3. Gym 100814C Connecting Graph 并查集+LCA

    Description standard input/output Statements Alex is known to be very clever, but Walter does not be ...

  4. Gym - 101243F Vitamins(思维+并查集)

    题意 有三种药丸,白色W>红色R>蓝色B,给你m个约束条件,问你n个药丸的颜色,不能确定颜色输出‘?’ 题解 如果1<2<3,只要找到2就能确定1和3的颜色 如果2=4,只要确 ...

  5. 【BZOJ2054】疯狂的馒头(并查集)

    /* 经典思路, 倒序并查集处理即可 */ #include<cstdio> #include<algorithm> #include<cstring> #incl ...

  6. 并查集【洛谷P1197】 [JSOI2008]星球大战

    P1197 [JSOI2008]星球大战 题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系 ...

  7. Artwork Gym - 101550A 离线并查集

    题目:题目链接 思路:每个空白区域当作一个并查集,因为正着使用并查集分割的话dfs会爆栈,判断过于复杂也会导致超时,我们采用离线反向操作,先全部涂好,然后把黑格子逐步涂白,我们把每个空白区域当作一个并 ...

  8. Codeforces Gym 100463E Spies 并查集

    Spies Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100463/attachments Desc ...

  9. Gym - 100625G Getting Through 计算几何+并查集

    http://codeforces.com/gym/100625/attachments/download/3213/2013-benelux-algorithm-programming-contes ...

随机推荐

  1. luogu 3958 奶酪

    noip2017 D2T1 奶酪 某zz选手没有想到可以用并查集来做,直接用了dijskstra,结果被ccf老爷机卡成了70分 题目大意: 现有一块大奶酪,它的高度为 h,它的长度和宽度我们可以认为 ...

  2. 洛谷P1365 WJMZBMR打osu! / Easy——期望DP

    题目:https://www.luogu.org/problemnew/show/P1365 平方和怎样递推? 其实就是 (x+1)^2 = x^2 + 2*x + 1: 所以我们要关注这里的 x — ...

  3. 3-1 vue生存指南 - todolist实现-数据渲染

    由于Vue.js作者是中国人,会说汉语,所以国内生态会更好一点.Vue.js作者是尤雨溪,

  4. bzoj 1833: [ZJOI2010]count 数字计数【数位dp】

    非典型数位dp 先预处理出f[i][j][k]表示从后往前第i位为j时k的个数,然后把答案转换为ans(r)-ans(l-1),用预处理出的f数组dp出f即可(可能也不是dp吧--) #include ...

  5. 关于Webpack的的认识及傻瓜式教学

    刚学习了Webpack,ememememememememem就赶脚是一个打包工具,将js.css.json.img等等通通打包为最终的文件,最后渲染为一个页面. 也是终于捋清了Webpack的思路,在 ...

  6. shiro vue 前后端分离中模拟登录遇到的坑

    系统采用jeeplus框架(ssm+redis+shiro+mongodb+redis),默认是了JSP未做前后端分离,由于业务需要已经多终端使用的需求(H5.小程序等),需要实现前后端分离.但是由于 ...

  7. UVa 101 - The Blocks Problem STL

    题目:给你n个方块,有四种操作: .move a onto b,把a和b上面的方块都放回原来位置,然后把a放到b上面: .move a over b,把a上面的放回原处,然后把a放在b所在的方块堆的上 ...

  8. Java多线程(五)停止线程 在沉睡中停止线程

    在沉睡中停止线程会抛出异常 public class SleepInterruptDemo extends Thread { public void run() { super.run(); try ...

  9. 生成 Guid

    //生成Guid    function getGuidGenerator() {        var S4 = function () {            return (((1 + Mat ...

  10. BFS HDOJ 1728 逃离迷宫

    题目传送门 /* BFS:三维BFS,加上方向.用dp[x][y][d]记录当前需要的最少转向数 */ #include <cstdio> #include <algorithm&g ...