题目链接

Islands

Time Limit: 30000/10000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
Submit Status

Deep in the Carribean, there is an island even stranger than the Monkey Island, dwelled by Horatio Torquemada Marley. Not only it has a rectangular shape, but is also divided into an n×mn×m grid. Each grid field has a certain height. Unfortunately, the sea level started to raise and in year ii, the level is ii meters. Another strange feature of the island is that it is made of sponge, and the water can freely flow through it. Thus, a grid field whose height is at most the current sea level is considered flooded.Adjacent unflooded fields (i.e., sharing common edge) create unflooded areas. Sailors are interested in the number of unflooded areas in a given year.

An example of a 4×54×5 island is given below. Numbers denote the heights of respective fields in meters.Unflooded fields are darker; there are two unflooded areas in the first year and three areas in the second year.

Input

Multiple Test Cases

The input contains several test cases. The first line of the input contains a positive integer Z≤20Z≤20,denoting the number of test cases. Then ZZ test cases follow, each conforming to the format described in section Single Instance Input. For each test case, your program has to write an output conforming to the format described in section Single Instance Output.

Single Instance Input

The first line contains two numbers nn and mm separated by a single space, the dimensions of the island, where 1≤n,m≤10001≤n,m≤1000. Next nn lines contain mm integers from the range [1,109][1,109] separated by single spaces, denoting the heights of the respective fields. Next line contains an integer TT (1≤T≤1051≤T≤105). The last line contains TT integers tjtj , separated by single spaces, such that 0≤t1≤t2≤⋯≤tT≤1090≤t1≤t2≤⋯≤tT≤109

Output

Single Instance Output

Your program should output a single line consisting of TT numbers rjrj , where rjrj is the number of unflooded areas in year tjtj . After every number ,you must output a single space!

Sample input and output

Sample Input Sample Output
1
4 5
1 2 3 3 1
1 3 2 2 1
2 1 3 4 3
1 2 2 2 2
5
1 2 3 4 5
2 3 1 0 0

Source

Central European Programming Contest 2009
 

题目大意:有一个岛屿是n*m的长方形的,每个格子的高度会给定,然后这个地方的水位会逐年上涨,在第i年时水位是i。就是说,所有高度<=i的格子都会被淹没。求没有被淹没的区域有几块(如果两个格子有公共边就认为它们属于同一个区域)。

现在给出n和m(1<=n,m<=1000),以及每个格子的高度([1,10^9]),然后有T([1,10^5])次查询,再给出t1,t2,,,(0,10^9),对于ti保证t这个序列是上升的。

 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long Ull;
#define MM(a,b) memset(a,b,sizeof(a));
const double eps = 1e-10;
const int inf = 0x3f3f3f3f;
const double pi=acos(-1);
const int maxn=1000;
int t[100000+10],ans[100000+10];
int dx[5]={-1,1,0,0};
int dy[5]={0,0,1,-1};
int n,m; struct node{
int x,y,h,id;
bool operator<(const node b) const
{
return this->h<b.h;//逆序考虑
}
}ne[maxn*maxn+10];
int par[maxn*maxn+10]; int findr(int id)
{
if(par[id]!=id)
par[id]=findr(par[id]);
return par[id];
} void unite(int i,int j)
{
int ri=findr(i);
int rj=findr(j);
if(ri!=rj) par[ri]=rj;
} int inmap(int x,int y)
{
return x>=1&&x<=n&&y>=1&&y<=m;
} priority_queue<node> q;//元素多了的话优先队列还是要开到外面的
int main()
{
int cas;
scanf("%d",&cas);
while(cas--)
{
MM(ans,0);
scanf("%d %d",&n,&m);
int sz=0;
while(q.size()) q.pop();//清空 for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&ne[++sz].h);
ne[sz].x=i;
ne[sz].y=j;
ne[sz].id=(i-1)*m+j;
par[sz]=ne[sz].id;
q.push(ne[sz]);
}
int w;
scanf("%d",&w);
for(int i=1;i<=w;i++) scanf("%d",&t[i]); for(int k=w;k>=1;k--)
{
ans[k]=ans[k+1];//当前集合在后一时刻的基础上
while(q.size())
{
node cur=q.top();
if(cur.h<=t[k]) break;
q.pop();
ans[k]++;//每个节点刚出现时都是一个独立的 for(int i=0;i<=3;i++)
{
int x=cur.x+dx[i];
int y=cur.y+dy[i];
int id=(x-1)*m+y;
if(ne[id].h<=t[k]||!inmap(x,y)) continue; int rx=findr(cur.id);//因为cur的父节点会随着合并而更新,所以需 //要再搜索一次
int ry=findr(id);
if(rx!=ry)
{
unite(rx,ry);
ans[k]--;//可以进行合并的话,集合数减1
}
}
}
}
for(int i=1;i<=w;i++)
printf("%d ",ans[i]);
printf("\n");
}
return 0;
}

  分析:并查集神题啊,暴搜肯定超时的,因为下一个时间的集合数是肯定在这一个时刻的集合的基础上减少的,所以可以考虑并查集,但是并查集是进行连接点的而不是删除点的,怎么办呢?把时间反过来逆向思考就好,最后还要注意,每次进行集合间的合并后,下次再用到该点时还要再查找一次。

其实可以用图来理解,每一个节点刚开始都是独立的,故增1,然后每一次合并时相当于连接了一条边,

集合数就会减1,因此一个集合最终只会增1,当然,如果已经在同一个集合的话就不能进行连接了,因为

不能产生环;

 wa代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long Ull;
#define MM(a,b) memset(a,b,sizeof(a));
const double eps = 1e-;
const int inf = 0x3f3f3f3f;
const double pi=acos(-);
const int maxn=;
int t[+],ans[+];
int dx[]={-,,,};
int dy[]={,,,-};
int n,m; struct node{
int x,y,h,id;
bool operator<(const node b) const
{
return this->h<b.h;
}
}ne[maxn*maxn+];
int par[maxn*maxn+]; int findr(int id)
{
if(par[id]!=id)
par[id]=findr(par[id]);
return par[id];
} void unite(int i,int j)
{
int ri=findr(i);
int rj=findr(j);
if(ri!=rj) par[ri]=rj;
} int main()
{
int cas;
scanf("%d",&cas);
while(cas--)
{
scanf("%d %d",&n,&m);
int sz=;
priority_queue<node> q;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
scanf("%d",&ne[++sz].h);
ne[sz].x=i;
ne[sz].y=j;
ne[sz].id=(i-)*m+j;
par[sz]=-;
q.push(ne[sz]);
}
int w;
scanf("%d",&w);
for(int i=;i<=w;i++) scanf("%d",&t[i]); for(int k=w;k>=;k--)
{
ans[k]=ans[k+];
while()
{
node cur=q.top();
if(cur.h<=t[k]) break;
q.pop();
if(par[cur.id]==-)
{
ans[k]++;
par[cur.id]=cur.id;
} int rx=findr(cur.id);
for(int i=;i<=;i++)
{
int x=cur.x+dx[i];
int y=cur.y+dy[i];
int id=(x-)*m+y;
int ry=findr(id);
if(ne[id].h<=t[i]) continue;
if(par[id]==-) ans[k]++;
if(rx!=ry)
{
unite(rx,ry);
ans[k]--;
}
}
}
}
for(int i=;i<=w;i++)
printf("%d ",ans[i]);
}
return ;
}

CDOJ 203 并查集+优先队列 好题的更多相关文章

  1. poj 2236:Wireless Network(并查集,提高题)

    Wireless Network Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 16065   Accepted: 677 ...

  2. poj 2524:Ubiquitous Religions(并查集,入门题)

    Ubiquitous Religions Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 23997   Accepted:  ...

  3. poj 1611:The Suspects(并查集,经典题)

    The Suspects Time Limit: 1000MS   Memory Limit: 20000K Total Submissions: 21472   Accepted: 10393 De ...

  4. hrbustoj 1073:病毒(并查集,入门题)

    病毒Time Limit: 1000 MS Memory Limit: 65536 KTotal Submit: 719(185 users) Total Accepted: 247(163 user ...

  5. 并查集+优先队列+启发式合并 || 罗马游戏 || BZOJ 1455 || Luogu p2713

    题面:P2713 罗马游戏 题解: 超级大水题啊,特别水.. 并查集维护每个人在哪个团里,优先队列维护每个团最低分和最低分是哪位,然后每次判断一下哪些人死了,随便写写就行 并查集在Merge时可以用启 ...

  6. “玲珑杯”ACM比赛 Round #7 B -- Capture(并查集+优先队列)

    题意:初始时有个首都1,有n个操作 +V表示有一个新的城市连接到了V号城市 -V表示V号城市断开了连接,同时V的子城市也会断开连接 每次输出在每次操作后到首都1距离最远的城市编号,多个距离相同输出编号 ...

  7. Codeforces Round #212 (Div. 2) D. Fools and Foolproof Roads 并查集+优先队列

    D. Fools and Foolproof Roads   You must have heard all about the Foolland on your Geography lessons. ...

  8. Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) A B C D 水 模拟 并查集 优先队列

    A. Broken Clock time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

  9. 并查集基础 模板题 hdu1232 畅通工程

    模板题 引入并查集——一则有趣的故事 为了解释并查集的原理,我将举一个更有趣的例子.话说江湖上散落着各式各样的大侠,有上千个之多.他们没有什么正当职业,整天背着剑在外面走来走去,碰到和自己不是一路人的 ...

随机推荐

  1. poj1220(短除法实现任意进制转换)

    题目链接:https://vjudge.net/problem/POJ-1220 题意:给定a进制的大数s,将其转换为b进制.其中2<=a,b<=62. 题意:一般进制转换是以10进制为中 ...

  2. etcd租约机制

    新建租约 新建一个过期时间为120s的租约 # etcdctl lease grant lease 018f6d7bb11aba0d granted with TTL(120s) 查看新建的租约信息 ...

  3. [转帖]Windows与Linux的命令行命令对比

    Windows与Linux的命令行命令对比 https://www.cnblogs.com/sztom/p/10785140.html * Windows不区分大小写,Linux区分大小写的. sn ...

  4. 并发之AQS原理(二) CLH队列与Node解析

    并发之AQS原理(二) CLH队列与Node解析 1.CLH队列与Node节点 就像通常医院看病排队一样,医生一次能看的病人数量有限,那么超出医生看病速度之外的病人就要排队. 一条队列是队列中每一个人 ...

  5. 【6.28校内test】T3 【音乐会】道路千万条

    [音乐会]道路千万条[题目链接] 首先,你可以忽略上面的一大坨题面,只需要看说明的那一小部分就好啦. 然后理解题意: 就是说我们要给这n-1个运算符指定一个顺序,统计所有值为true的方案数pt,统计 ...

  6. 重写移动端滚动条[iScroll.js核心代码]

    最近写组件库的时后,发现这个滚动条是真的丑啊,决定重新撸一个滚动条: 首先咱们回顾一下移动端浏览器滚动条特性: 滚动条在开始滚动时渐显,滚动结束后渐隐 滚动条不占内容区宽度,悬浮固定 滚动条高度(深灰 ...

  7. css阴影——box-shadow

    1.语法 box-shadow: h-shadow v-shadow blur spread color inset;      box-shadow: 水平阴影  垂直阴影 模糊距离 阴影大小 阴影 ...

  8. bcdedit删除uefi多余项

    1.检查是否有多余的启动项:用管理员权限的cmd运行Bcdedit /enum firmware 2.保存现在的所有引导项Bcdedit /export savebcdsavebcd是导出的文件名 3 ...

  9. laravel5.8 表单验证

    'name' => 'required|unique:posts|max:255', // posts 表名 源码  vendor\laravel\framework\src\Illuminat ...

  10. VMware 问题

    桥接模式下,小鸡上不了网问题 多网卡导致的问题 解决:编辑-虚拟网络编辑器 选择vmnet0,然后点击右下角更改设置 把自动改为指定要桥接的网卡,然后点击确定,测试看看.