首页 技术 正文
技术 2022年11月21日
0 收藏 616 点赞 2,121 浏览 5179 个字

题目链接

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.

CDOJ    203     并查集+优先队列   好题

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 ;
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,909
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,434
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,249
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,060
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,692
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,730