BZOJ1104 : [POI2007]洪水pow

从小到大枚举高度i:

对于所有高度为i的点x,将它与它四周相邻的高度不超过i的点所在的集合合并

对于所有高度为i的城市x,如果它所在集合没有放置水泵,则需要放置

并查集维护,时间复杂度$O(nm)$。

#include<cstdio>
#define N 1010
int n,m,i,j,k,x,y,a[N][N],id[N][N],f[N*N],v[N*N],cnt,dx[4]={-1,1,0,0},dy[4]={0,0,-1,1},ans;
struct E{int x,y;E*nxt;}*g[N],*h[N],pool[N*N*2],*cur=pool,*p;
inline void addg(int z,int x,int y){p=cur++;p->x=x;p->y=y;p->nxt=g[z];g[z]=p;}
inline void addh(int z,int x,int y){p=cur++;p->x=x;p->y=y;p->nxt=h[z];h[z]=p;}
inline void read(int&a){
  char c;bool f=0;a=0;
  while(!((((c=getchar())>=‘0‘)&&(c<=‘9‘))||(c==‘-‘)));
  if(c!=‘-‘)a=c-‘0‘;else f=1;
  while(((c=getchar())>=‘0‘)&&(c<=‘9‘))(a*=10)+=c-‘0‘;
  if(f)a=-a;
}
int F(int x){return f[x]==x?x:f[x]=F(f[x]);}
inline void merge(int x,int y){if(F(x)!=F(y))v[f[y]]|=v[f[x]],f[f[x]]=f[y];}
int main(){
  for(read(n),read(m),i=1;i<=n;i++)for(j=1;j<=m;j++){
    read(a[i][j]);
    if(a[i][j]>0)addg(a[i][j],i,j);else a[i][j]=-a[i][j];
    id[i][j]=++cnt,addh(a[i][j],i,j);
  }
  for(i=1;i<=cnt;i++)f[i]=i;
  for(i=0;i<=1000;i++){
    for(p=h[i];p;p=p->nxt)for(k=0;k<4;k++){
      x=p->x+dx[k],y=p->y+dy[k];
      if(!id[x][y]||a[x][y]>a[p->x][p->y])continue;
      merge(id[p->x][p->y],id[x][y]);
    }
    for(p=g[i];p;p=p->nxt)if(!v[F(id[p->x][p->y])])v[f[id[p->x][p->y]]]=1,ans++;
  }
  return printf("%d",ans),0;
}

  

时间: 2024-10-09 23:34:30

BZOJ1104 : [POI2007]洪水pow的相关文章

[POI2007]洪水pow 题解

[POI2007]洪水pow 时间限制: 5 Sec  内存限制: 128 MB 题目描述 AKD市处在一个四面环山的谷地里.最近一场大暴雨引发了洪水,AKD市全被水淹没了.Blue Mary,AKD市的市长,召集了他的所有顾问(包括你)参加一个紧急会议.经过细致的商议之后,会议决定,调集若干巨型抽水机,将它们放在某些被水淹的区域,而后抽干洪水.你手头有一张AKD市的地图.这张地图是边长为m*n的矩形,被划分为m*n个1*1的小正方形.对于每个小正方形,地图上已经标注了它的海拔高度以及它是否是A

[POI2007]洪水pow

问题 E: [POI2007]洪水pow 时间限制: 5 Sec  内存限制: 128 MB 题目描述 AKD市处在一个四面环山的谷地里.最近一场大暴雨引发了洪水,AKD市全被水淹没了.Blue Mary,AKD市的市长,召集了他的所有顾问(包括你)参加一个紧急会议.经过细致的商议之后,会议决定,调集若干巨型抽水机,将它们放在某些被水淹的区域,而后抽干洪水.你手头有一张AKD市的地图.这张地图是边长为m*n的矩形,被划分为m*n个1*1的小正方形.对于每个小正方形,地图上已经标注了它的海拔高度以

[POI2007]洪水pow 并查集

我们先得出一个结论:水泵要建在城市上.因为如果在非城市上建能把其他一些城市抽干,那么在城市上建也是一个效果(自己画图感性理解一下) 然后我们明白抽水的条件:周围的高度要>=自身的高度,这样会抽完它.如果低的话,会降低旁边位置的水位(这很重要) 然后我们枚举每一个城市,看它用不用建造.这样在每一个城市,枚举所有位置,看这个位置能不能被四周的抽干,这样用并查集维护,能抽干的都是一个祖先 这样枚举完一遍后,看这个城市所连的并查集有没有被抽干,如果没有,就在那里建造即可 #include<iostre

BZOJ 1104 POI2007 洪水pow 并查集

题目大意:给定一张地势图,所有的点都被水淹没,现在有一些关键点,要求放最少的水泵使所有关键点的水都被抽干 前排感谢VFK 首先可以证明一定存在一种最优解使所有的水泵都在关键点上 那么我们将所有关键点按照高度排序,从小到大枚举每个关键点 对于每个关键点x,我们将所有高度小于等于x点的点都加入并查集并将相邻的合并 由于x是并查集中最高的点,因此并查集中任意一个点放置水泵都会导致点x被抽干 故如果x所在并查集中已经放置过水泵,则无需在x点放置水泵 否则就要在x点放置一个水泵 时间复杂度O(mnlog(

洪水 Pow

Description AKD市处在一个四面环山的谷地里.最近一场大暴雨引发了洪水,AKD市全被水淹没了.Blue Mary,AKD市的市长,召集了他的所有顾问(包括你)参加一个紧急会议.经过细致的商议之后,会议决定,调集若干巨型抽水机,将它们放在某些被水淹的区域,而后抽干洪水. 你手头有一张AKD市的地图.这张地图是边长为m*n的矩形,被划分为m*n个1*1的小正方形.对于每个小正方形,地图上已经标注了它的海拔高度以及它是否是AKD市的一个组成部分.地图上的所有部分都被水淹没了.并且,由于这张

联赛之前的题表(已完成)汇总(可能有遗漏)

联赛之前的搞搞(其实是懒得分类) 博弈论 poj3537 poj1704 hdu5996两个插头 HDU1693 Eat the Trees COGS1283. [HNOI2004] 邮递员kdtree板子1941: [Sdoi2010]Hide and Seek旋转卡壳 pj2187凸包 cogs896 bzoj2829 信用卡凸包莫比乌斯反演基础 bzoj 4173 zhao gui lv bzoj 3529 mobiwus bzoj 4407 mobiwus bzoj 2818 mobiw

poi2007

序:为什么写poi,zy说poi都是思路题目,不像hnoi妈的数据结构队..... 1.bzoj1102 题目大意:定义了一个山谷和山峰,求他们数量. 题解:这种题bfs咯,在bfs的时候记录一下相邻的比我大的有多少,比我小的有多少,然后更新答案: 代码: 1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cmath&

LeetCode 50 Pow(x, n)(Math、Binary Search)(*)

翻译 实现pow(x, n). 原文 Implement pow(x, n). 分析 首先给大家推荐维基百科: zh.wikipedia.org/wiki/二元搜尋樹 en.wikipedia.org/wiki/Binary_search_tree 其次,大家也可以看看类似的一道题: LeetCode 69 Sqrt(x)(Math.Binary Search)(*) 然而这题我还是没有解出来,看看别人的解法-- class Solution { private: double myPowHel

Pow(x, n)

Implement pow(x, n). class Solution { public: double myPow(double x, int n) { // Start typing your C/C++ solution below // DO NOT write int main() function if(n<0) { if(n==INT_MIN) return 1.0 / (myPow(x,INT_MAX)*x); else return 1.0 / myPow(x,-n); } i