题目:

思路:

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. mac ox终端显示 bogon的问题

    mac终端显示如果正常应该是电脑名称(偏好设置-共享)的,但是细心的我们会发现,当电脑换了网络环境之后,可能就会出现终端上显示为主机名为:bogon,一查bogon这个单词是虚拟.虚伪的意思.     ...

  2. emma中文显示乱码问题解决(ubutnu)

    vim -/.emma/emmarc 找到  db_encoding=latin1 改为  db_encoding=utf8  然后重新运行emma,此时发现还是乱码,不要着急,在执行所有的sql语句 ...

  3. C#面向过程之冒泡排序

    //定义一个数组,准备冒泡排序 ,,-,,,,-,}; //定义一个中间变量 ; //n个数字比较需要进行n-1次比较 ; j < arr.Length - - i; j++) { //每一趟的 ...

  4. C#面向过程之编译原理、变量、运算符

    .net基础:.net与C# .net是一个平台 c#是一门语言 .net的用途a.桌面应用程序 b.网站应用程序 c.专业游戏开发(XBOX360) d.嵌入式设备软件开发 e.智能手机APP开发 ...

  5. E20170603-hm

    current   adj. 现在的; 最近的; 流行的; 流传的; currency   n. 货币; 通用,流通 delimiter n. 定界符,分隔符; precision  n. 精确度,准 ...

  6. Nginx(三) 常用配置整理

    #定义Nginx运行的用户和用户组 user www www; #nginx进程数,建议设置为等于CPU总核心数. worker_processes 8; #全局错误日志定义类型,[ debug | ...

  7. Elementui tabs组件内添加组件

    1. Elementui tabs组件内添加组件 1.1. 需求 今天的一个需求是在后台框架的基础上添加tab页,结果页面如下 原本上述红框内的内容是不存在的,直接点击左侧菜单栏进行页面跳转,现加了t ...

  8. HTML <input>标签属性

  9. ACM_Fibonacci数(同余)

    Fibonacci数 Time Limit: 2000/1000ms (Java/Others) Problem Description: 斐波那契数列定义如下:f(0)=0,f(1)=1,f(n+2 ...

  10. web api 二

    接着上一回说,上回说到,web api有几种访问方式,具体有几种,我还真没去研究过,但是这里打算从get.post.put.delete四种请求方式分别谈谈基础类型(包括int/string/date ...