【Openjudge】岛屿(并查集)

题目链接

此题是并查集。考虑到水位不断上涨,所以将时间倒转。先统计最后一天的联通块个数,每一天浮出水面的块进行计算。复杂度O(玄学)。

代码如下

#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;

short u[5]={0,0,1,0,-1};
short w[5]={0,1,0,-1,0};

int n,m;

inline long long read(){
  long long num=0,f=1;
  char ch=getchar();
  while(!isdigit(ch)){
      if(ch==‘-‘)f=-1;
      ch=getchar();
  }
  while(isdigit(ch)){
      num=num*10+ch-‘0‘;
      ch=getchar();
  }
  return num*f;
}

struct Point{
  short x,y;
  int h;
  bool operator <(const Point &a)const{
     return h
  }
}mp[10000000];
int num;
int Map[3001][3001];
int que[1000000];
int ans[1000000];
int father[10000000];
bool jd[3001][3001];

int find(int x){
  if(father[x]!=x)father[x]=find(father[x]);
  return father[x];
}

inline void Union(int x,int y){
  x=find(x);y=find(y);
  father[y]=x;
}

inline int query(int i,int j){
   return (i-1)*m+j;
}

int main(){
  n=read(),m=read();
  for(int i=1;i<=n*m+1;++i)    father[i]=i;
  int s;
  for(int i=1;i<=n;++i)
  for(int j=1;j<=m;++j){
      s=read();
      mp[++num]=(Point){i,j,s};
      Map[i][j]=s;
  }
  sort(mp+1,mp+num+1);
  int T=read();
  for(int i=1;i<=T;++i)    que[i]=read();
  int cnt=1;
  for(int i=T;i>=1;--i){
      ans[i]=ans[i+1];
      while(mp[cnt].h>que[i]&&cnt<=n*m){
          jd[mp[cnt].x][mp[cnt].y]=1;
          ans[i]++;
          for(int j=1;j<=4;++j){
              short x=mp[cnt].x+u[j];
              short y=mp[cnt].y+w[j];
              if(x>0&&y>0&&x<=n&&y<=m&&Map[x][y]>que[i]&&jd[x][y]&&find(query(x,y))!=find(query(mp[cnt].x,mp[cnt].y))){
                  Union(query(x,y),query(mp[cnt].x,mp[cnt].y));
                  ans[i]--;
              }
          }
          cnt++;
      }
  }
  for(int i=1;i<=T;++i)printf("%d ",ans[i]);
  return 0;
}
时间: 2024-10-03 02:03:06

【Openjudge】岛屿(并查集)的相关文章

【openjudge】C15C Rabbit&#39;s Festival CDQ分治+并查集

题目链接:http://poj.openjudge.cn/practice/C15C/ 题意:n 点 m 边 k 天.每条边在某一天会消失(仅仅那一天消失).问每一天有多少对点可以相互到达. 解法:开始不会做,参考的YYN的题解:http://blog.csdn.net/u013368721/article/details/45725181 学习了这种CDQ加并查集的做法,可以说是非常的巧妙了.复杂度可以保证在:O(KlogklogK)的范围. //CDQ + DSU #include <bit

(算法)并查集及其应用

题目: 某国家有N个小岛组成,经过多年的基础设施累积,若该岛屿之间建立若干桥梁,先重新完善该国的行政区划,规定只要有桥梁连接的岛屿则归属于同一个城市(可以通过其他岛屿中转),问该国可以划分为多少个城市? 思路: 并查集 代码: #include<iostream> #include<set> using namespace std; class UnionFindSet{ private: int m_nN; int* m_pParent; public: UnionFindSet

BZOJ 2733: [HNOI2012]永无乡(treap + 启发式合并 + 并查集)

不难...treap + 启发式合并 + 并查集 搞搞就行了 ---------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #define rep(i, n) for(int i = 0; i &l

bzoj 1196: [HNOI2006]公路修建问题 二分+并查集

题目链接 1196: [HNOI2006]公路修建问题 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1576  Solved: 909[Submit][Status][Discuss] Description OI island是一个非常漂亮的岛屿,自开发以来,到这儿来旅游的人很多.然而,由于该岛屿刚刚开发不久,所以那里的交通情况还是很糟糕.所以,OIER Association组织成立了,旨在建立OI island的交通系统. OI isla

bzoj 2733 永无乡 - 并查集 - 线段树

永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛.如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的.现在有两种操作:B x y 表示在岛 x 与岛 y 之间修建一座新桥.Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k 小的岛是哪 座,请你输

算法初级面试题05——哈希函数/表、生成多个哈希函数、哈希扩容、利用哈希分流找出大文件的重复内容、设计RandomPool结构、布隆过滤器、一致性哈希、并查集、岛问题

今天主要讨论:哈希函数.哈希表.布隆过滤器.一致性哈希.并查集的介绍和应用. 题目一 认识哈希函数和哈希表 1.输入无限大 2.输出有限的S集合 3.输入什么就输出什么 4.会发生哈希碰撞 5.会均匀分布,哈希函数的离散性,打乱输入规律 public class Code_01_HashMap { public static void main(String[] args) { HashMap<String, String> map = new HashMap<>(); map.p

[拓扑排序][DP][Tarjan][并查集]JZOJ 4253 QYQ在艾泽拉斯

Description 在艾泽拉斯的无尽之海里,有着一群不为人知的由各个种族的冒险者统治的岛屿,这些岛屿都很庞大,足以在上面建造许多的城市,城市之间有一些单向道路连接.有一天,QYQ无意中发现了这些岛屿,并且发现在每个城市的地下都或多或少埋藏着一些装备.金币.宝物……可是正当QYQ兴奋不已打算全部把它们拿走时,他却惊奇的发现你的魔法在这里被限制住了,唯一可用的技能就是闪现,而且魔法只够他使用K次这个技能了,每次使用这个技能QYQ只能从一个岛屿上闪现到另外一个岛屿上.每一个岛屿只能登上一次,QYQ

Leetcode-并查集

200.岛屿数量 https://leetcode-cn.com/problems/number-of-islands/ 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. 示例: 输入: 11000 11000 00100 00011 输出: 3 解: 1. 转换为染色问题: 遍历所有节点 if node ==1: count ++; 将node附近陆地节点赋0 e

CodeForces 745C Hongcow Builds A Nation 并查集

题意: 给了你n个城市 m条边 k个政府 每个政府管辖的区域内不能和其他政府的区域有相连 即政府之间不存在路径 问你在维护这种关系的同时 最多再加多少条边 思路: 先找出来每个联通块 再找出来没有归属的孤立的点 把他们都放到最大的联通块里 然后每个联通块之间的点两两连边是n*(n-1)/2条边 最后算出来的ans-m就好了 (看别人的博客学了一个max_element 1 #include<bits/stdc++.h> 2 #define cl(a,b) memset(a,b,sizeof(a