hust 1385 islands 并查集+搜索

islands

Time Limit: 1 Sec  Memory Limit: 256 MB

题目连接

http://acm.hust.edu.cn/problem/show/1385

Description

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 x m grid. Each grid field has a certain height. Unfortunately, the sea level started to raise and in year i, the level is i 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 4x5 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≤20,denoting the number of test cases. Then Z 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 n and m separated by a single space, the dimensions of the island, where 1≤n,m≤1000. Next n lines contain m integers from the range [1,109] separated by single spaces, denoting the heights of the respective fields. Next line contains an integer T (1≤T≤105). The last line contains T integers tj , separated by single spaces, such that 0≤t1≤t2≤?≤tT≤109

Output

Single Instance Output

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

Sample Input

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

Sample Output

2 3 1 0 0

HINT

题意

一个n*m的图上,每一个区域都有一个权值,然后每个权值

然后有k个查询,给你n个d[i]

每次都会让大于d[i]的点起来,然后问你每次分别有多少个联通分量

题解:

首先我们离线做,然后我们排序,从大到小弄

这样子我们就可以很轻松的想到一个动态转移

然后我们再拿并查集维护一下,再搞一搞就好了

代码:

//qscqesze
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 1001
#define mod 10007
#define eps 1e-9
//const int inf=0x7fffffff;   //无限大
const int inf=0x3f3f3f3f;
/*
inline ll read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int buf[10];
inline void write(int i) {
  int p = 0;if(i == 0) p++;
  else while(i) {buf[p++] = i % 10;i /= 10;}
  for(int j = p-1; j >=0; j--) putchar(‘0‘ + buf[j]);
  printf("\n");
}
*/
//**************************************************************************************

int fa[maxn*maxn],ans,n,m,k,tot,q[maxn*maxn],vis[maxn][maxn];
int g[maxn][maxn];
struct node
{
    int x,y,z;
};
bool cmp2(int a,int b)
{
    return a>b;
}
bool cmp(node a,node b)
{
    return a.z>b.z;
}
node a[maxn*maxn];
int id(int x,int y)
{
    return 1001*x+y;
}
int fi(int x)
{
    return x == fa[x] ? x : fa[x] = fi(fa[x]);
}

void un(int a, int b)
{
    a = fi(a);
    b = fi(b);
    if(a == b)
    {
        return;
    }
    fa[b] = a;
    ans--;
}
int judge(int x,int y)
{
    if(x>=0 && x<n && y>=0 && y<m)
        if(vis[x][y])
            return 1;
    return 0;
}
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
void init()
{
    memset(fa,0,sizeof(fa));
    memset(a,0,sizeof(a));
    ans=0;
    memset(q,0,sizeof(q));
    memset(vis,0,sizeof(vis));
    memset(g,0,sizeof(g));
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        init();
        scanf("%d%d",&n,&m);
        tot=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                scanf("%d",&a[tot].z);
                a[tot].x=i;
                a[tot++].y=j;
                fa[id(i,j)]=id(i,j);
            }
        }
        sort(a,a+tot,cmp);
        scanf("%d",&k);
        for(int i=0;i<k;i++)
            scanf("%d",&q[i]);
        sort(q,q+k,cmp2);
        vector<int> qq;
        int pic=0;
        for(int i=0;i<k;i++)
        {
            while(pic<tot&&a[pic].z>q[i])
            {
                ans++;
                int x=a[pic].x,y=a[pic].y;
                vis[x][y]=1;
                for(int j=0;j<4;j++)
                {
                    int xx=x+dx[j],yy=y+dy[j];
                    if(judge(xx,yy))
                    {
                        un(id(x,y),id(xx,yy));
                    }
                }
                pic++;
            }
            qq.push_back(ans);
        }
        for(int i=qq.size()-1;i>=0;i--)
        {
            printf("%d ",qq[i]);
        }
        printf("\n");
    }
}
时间: 2024-10-10 02:13:42

hust 1385 islands 并查集+搜索的相关文章

HDU3926Hand in Hand(搜索 或 并查集)

Problem Description In order to get rid of Conan, Kaitou KID disguises himself as a teacher in the kindergarten. He knows kids love games and works out a new game called "hand in hand". Initially kids run on the playground randomly. When Kid say

CodeForces 510B 无向图找环的两种方法(搜索与并查集)

题目连接:http://codeforces.com/problemset/problem/510/B 解法: dfs 每次把父节点的值记录并传递下去,判断一下新达到节点: (1)没有走过 → 继续搜索: (2)走过&&不是父节点(对于本题步数也要>=4) → 找到环: 并查集 每个节点映射成 i*m+j从起点开始分别把它下面与于右面的节点加进来,如果发现有节点已经在集合中,那么环已经找到了. DFS: #include<cstdio> #include<cstdl

hdu 1198 Farm Irrigation (搜索或并查集)

Farm Irrigation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5818    Accepted Submission(s): 2521 Problem Description Benny has a spacious farm land to irrigate. The farm land is a rectangle

【搜索】【并查集】Codeforces 691D Swaps in Permutation

题目链接: http://codeforces.com/problemset/problem/691/D 题目大意: 给一个1到N的排列,M个操作(1<=N,M<=106),每个操作可以交换X Y位置上的数字,求可以得到的最大字典序的数列. 题目思路: [搜索][并查集] 这题可以用搜索或者并查集写,都能过. 把位置分成若干块,每一块里面的位置都是可以被这一块里另一个位置经过若干次调换的(类似强连通,位置可达). 然后把每一块位置里的 位置按从小到大排序,位置上的值按从大到小排序,依次填入位置

并查集的离线搜索([JSOI2008]星球大战)

很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,很快帝国又重新造出了他的超级武器.凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球.由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来.现在,反抗军首领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每一次

【NOIP模拟_54测试】【并查集】【二进制】【搜索】【区间序列类】

第一题 Mushroom的序列 大意: 给一个序列,求一段连续最长区间满足:最多改变一个数,使得区间是严格的上升子序列. 解: 直接扫描一遍,记一个最长上升子序列编号.然后从每一个编号为1 的点来判断是否可以将两个序列合并,有两种情况,讨论需要注意多种子情况...我可能想的比较复杂,所以第一遍写的时候少考虑了一些相等的情况,就WA 了一个点. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #i

并查集问题hdu 1232

Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可).问最少还需要建设多少条道路? Input 测试输入包含若干测试用例.每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M:随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号.为简单起见,城镇从1

【并查集题目总结】

[并查集题目总结] 问题一:并查集森林的连通分支数(经典,pre[ i ] == i ?) http://acm.hdu.edu.cn/showproblem.php?pid=1232 问题二:并查集森林所有连通分支最大元素个数(维持一个cnt[ ]数组) http://acm.hdu.edu.cn/showproblem.php?pid=1856 问题三:构造并查集森林过程中计数不能成环的边数(成环 等价于 根节点相同) http://acm.hust.edu.cn/vjudge/proble

并查集 (Union-Find Sets)及其应用

定义 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.常常在使用中以森林来表示. 集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并. 主要操作 初始化 把每个点所在集合初始化为其自身. 通常来说,这个步骤在每次使用该数据结构时只需要执行一次,无论何种实现方式,时间复杂度均为O(N). 查找 查找元素所在的集合,即根节点. 合并 将两个元素所在的集合合并为一个集合. 通常来说,合并之前,应先判断两个元素是否属于