题目链接

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. 20191209 Linux就该这么学(1-3)

    1. 部署虚拟环境安装 Linux 系统 RPM 是为了简化安装的复杂度,而 Yum软件仓库是为了解决软件包之间的依赖关系. 2. 新手必须掌握的Linux命令 通常来讲,计算机硬件是由运算器.控制器 ...

  2. Python xlsxwriter库 图表Demo

    折线图 import xlsxwriter # 创建一个excel workbook = xlsxwriter.Workbook("chart_line.xlsx") # 创建一个 ...

  3. 小记---------Hadoop的MapReduce基础知识

    MapReduce是一种分布式计算模型,主要用于搜索领域,解决海量数据的计算问题 MR由两个阶段组成:Map和Reduce,用户只需要实现map()和reduce()两个函数,即可实现分布式计算. 两 ...

  4. Windown Server 2008配置tomcat9虚拟路径

    一.用途 用于保存项目运产生的文件 二.步骤 1.修改conf\下的web.xml <!-- 找到listings将false改为true -->        <init-para ...

  5. Packet flow in l2(receive and transmit)

    Receive 1.  napi && none napi 讲网络收报过程,必然要涉及到网卡收报模型发展历史.总体上看,网络收报过经历了如下发展过程: 轮询 ---à 中断 ---à ...

  6. Paxos协议理解

    第三次报告: 理解Paxos协议 一. Paxos协议背景 什么是Paxos协议? 一般地,从客户端和服务器的角度,任何一个分布式系统都可以理解成由一个服务器集合和一个客户端集合组成,一个或多个客户端 ...

  7. Gym 101466(完整)

    题目链接 :点击此处 ## Problem A 题意: 给你n个数,重定义两个数之间的加法不进位,求这些数中两个数相加的最大值和最小值. 题解: 字典树.我们首先将前i-1为放入字典树中,然后在查询第 ...

  8. [.net core]3. Project 文件简介

    这是一个C#的空的.net core web app .net frame work的.csproj 要编辑的话,得先卸载项目,  .net core的.csproje不必要, .csproj 的文件 ...

  9. Unicode字符集,utf8编码,base64编码简单了解

    Unicode字符集,utf8编码,base64编码简单了解 Unicode字符集,ASCII,GB2312编码集合等,类似于不同的字典,不同的字符的编码,类似于字典中的字在哪一个页哪一排. 当不同系 ...

  10. s:schema报错问题

    解决方案: 删除所有<s:element ref="s:schema"/>标签 说明书改为本地文件