BZOJ3485 : [Baltic2012]peaks

首先将每个平原缩成一个点,建出图,相邻两个点之间的边权为它们高度的较小值。

用Kruskal算法求出这个图的最大生成树,每次合并两个连通块时新建一个点指向它们,得到一棵有根树。

对于每个点,求出它子树内最高的峰,那么对于每个叶子,在它到根的路径上二分查找即可。

时间复杂度$O(nm\log(nm))$。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=2005,M=200010;
int n,m,i,j,x,y,z,dx,dy,a[N][N],p[N][N],cb;
int cnt,is[M],h[M],f[M],son[M][2],ma[M],q[M],top,ans;
struct P{int x,y;P(){}P(int _x,int _y){x=_x,y=_y;}}b[M/2],fin[M/2];
inline bool cmp(const P&x,const P&y){return a[x.x][x.y]>a[y.x][y.y];}
inline bool cmp2(const P&a,const P&b){return a.x==b.x?a.y>b.y:a.x>b.x;}
inline void read(int&a){char c;while(!(((c=getchar())>=‘0‘)&&(c<=‘9‘)));a=c-‘0‘;while(((c=getchar())>=‘0‘)&&(c<=‘9‘))(a*=10)+=c-‘0‘;}
void dfs(int x,int y){
  p[x][y]=cnt;
  for(int i=x-1;i<=x+1;i++)for(int j=y-1;j<=y+1;j++){
    if(a[i][j]>a[x][y])is[cnt]=0;
    if(a[i][j]==a[x][y]&&!p[i][j])dfs(i,j);
  }
}
int F(int x){return f[x]==x?x:f[x]=F(f[x]);}
inline void merge(int x,int y,int z){
  if(!x||!y)return;
  x=F(x),y=F(y);
  if(x==y)return;
  h[++cnt]=z,f[cnt]=cnt;
  son[cnt][0]=x,son[cnt][1]=y;
  f[x]=f[y]=cnt;
}
void dfs2(int x){
  if(is[x])ma[x]=h[x];
  for(int i=0;i<2;i++){
    int y=son[x][i];
    if(!y)continue;
    dfs2(y);
    ma[x]=max(ma[x],ma[y]);
  }
}
inline void cal(int o){
  int l=1,r=top,t=0,mid;
  while(l<=r)if(ma[q[mid=(l+r)>>1]]>o)l=(t=mid)+1;else r=mid-1;
  fin[++ans]=P(o,h[q[t]]);
}
void dfs3(int x){
  if(is[x])cal(h[x]);
  q[++top]=x;
  for(int i=0;i<2;i++){
    int y=son[x][i];
    if(!y)continue;
    dfs3(y);
  }
  top--;
}
int main(){
  read(n),read(m);
  for(i=1;i<=n;i++)for(j=1;j<=m;j++)read(a[i][j]);
  for(i=1;i<=n;i++)for(j=1;j<=m;j++)if(!p[i][j])is[++cnt]=1,h[cnt]=a[i][j],dfs(i,j);
  for(i=1;i<=n;i++)for(j=1;j<=m;j++)b[++cb]=P(i,j);
  sort(b+1,b+cb+1,cmp);
  for(i=1;i<=cnt;i++)f[i]=i;
  for(i=1;i<=cb;i++){
    x=b[i].x,y=b[i].y,z=p[x][y];
    for(dx=x-1;dx<=x+1;dx++)for(dy=y-1;dy<=y+1;dy++)if(a[dx][dy]>=a[x][y])merge(p[dx][dy],z,a[x][y]);
  }
  dfs2(cnt),dfs3(cnt);
  sort(fin+1,fin+ans+1,cmp2);
  printf("%d\n",ans);
  for(i=1;i<=ans;i++)printf("%d %d\n",fin[i].x,fin[i].y);
  return 0;
}

  

时间: 2024-10-07 05:36:35

BZOJ3485 : [Baltic2012]peaks的相关文章

Science14年的聚类论文——Clustering by fast search and find of density peaks

这是一个比较新的聚类方法(文章中没看见作者对其取名,在这里我姑且称该方法为local density clustering,LDC),在聚类这个古老的主题上似乎最近一些年的突破不大,这篇文章算是很好的了,方法让人很有启发(醍醐灌顶),并且是发表在Science上,受到的关注自然非常大. 本文的核心亮点:1是用比较新颖的方法来确定聚类中心,2是采用距离的local density来进行聚类的划分.在这两点中,常见的Kmeans算法采用的方法是:用每一类的均值作为中点,用距离的最近的点来确定聚类划分

bzoj 3551: [ONTAK2010]Peaks加强版

Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来Q行,每行三个数v x k,表示一组询问.v=v xor lastans,x=x xor lastans,k=k xor lastans.如果lastans=-1则不变. Output 同3545 Sample Input Sample Output HINT [数据范围]同3545 Source

bzoj3551 [ONTAK2010]Peaks加强版

Description //[题目描述]同3545 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1. Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来Q行,每行三个数v x k,表

bzoj3545 [ONTAK2010]Peaks

3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 572  Solved: 164[Submit][Status] Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1. I

Science论文&quot;Clustering by fast search and find of density peaks&quot;学习笔记

"Clustering by fast search and find of density peaks"是今年6月份在<Science>期刊上发表的的一篇论文,论文中提出了一种非常巧妙的聚类算法.经过几天的努力,终于用python实现了文中的算法,下面与大家分享一下自己对算法的理解及实现过程中遇到的问题和解决办法. 首先,该算法是基于这样的假设:类簇中心被具有较低局部密度的邻居点包围,且与具有更高密度的任何点有相对较大的距离.对于每一个数据点,要计算两个量:点的局部密度和

Clustering by density peaks and distance

这次介绍的是Alex和Alessandro于2014年发表在的Science上的一篇关于聚类的文章[13],该文章的基本思想很简单,但是其聚类效果却兼具了谱聚类(Spectral Clustering)[11,14,15]和K-Means的特点,着实激起了我的极大的兴趣,该聚类算法主要是基于两个基本点: 聚类中心的密度高于其临近的样本点的密度 聚类中心与比其密度还高的聚类中心的距离相对较大 基于这个思想,聚类过程中的聚类中心数目可以很直观的选取,离群点也能被自动检测出来并排除在聚类分析外.无论每

bzoj 3545&amp;&amp;3551: [ONTAK2010]Peaks &amp;&amp;加强版 平衡树&amp;&amp;并查集合并树&amp;&amp;主席树

3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 635  Solved: 177[Submit][Status] Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1. I

Clustering by fast search and find of density peaks

"Clustering by fast search and find of density peaks"是20114年6月份在<Science>期刊上发表的的一篇论文,论文中提出了一种非常巧妙的聚类算法. 首先,该算法是基于这样的假设: (1)聚类中心密度要高 (2)高密度中心点之间的距离应该相对远一些. 异常点都会被排除,同时也和形状无关. 首先,这种方法不像原先的Kmeans那样随机初始种子点然后迭代,它是根据样本的密度峰值来确定聚类中心的,当然聚类中心确定之后,后面

Hadoop实现Clustering by fast search and find of density peaks

Hadoop实现Clustering by fast search and find of density peaks 本篇博客参考:Clustering by fast search and find of density peaks论文以及http://www.cnblogs.com/peghoty/p/3945653.html. Hadoop版本:2.6.0,Myeclipse:10.0 代码可在https://github.com/fansy1990/fast_cluster下载. 1.