【BZOJ5101】[POI2018]Powód

Description

在地面上有一个水箱,它的俯视图被划分成了n行m列个方格,相邻两个方格之间有一堵厚度可以忽略不计的墙,水箱与外界之间有一堵高度无穷大的墙,因此水不可能漏到外面。已知水箱内每个格子的高度都是[0,H]之间的整数,请统计有多少可能的水位情况。因为答案可能很大,请对10^9+7取模输出。两个情况不同当且仅当存在至少一个方格的水位在两个情况中不同。

Input

第一行包含三个正整数n,m,H(n*m<=500000,1<=H<=10^9)。
接下来n行,每行m-1个整数a[i][j](1<=a[i][j]<=H),表示(i,j)和(i,j+1)之间的墙的高度。
接下来n-1行,每行m个整数b[i][j](1<=b[i][j]<=H),表示(i,j)和(i+1,j)之间的墙的高度。

Output

输出一行一个整数,即方案数模10^9+7的结果。

Sample Input

3 2 2
1
1
1
1 2
1 1

Sample Output

65
HINT
要么全部格子水位都是2,要么全部格子水位都在[0,1]之间,共1+2^6=65种情况。

题解:先将所有边按高度排序,然后从小到大枚举所有边,用并查集维护格子的连通性。在并查集合并的时候统计一下方案数就好。

具体地,我们用g表示当前连通块的方案数,h表示这个连通块当前的水位高度,设当前水位为now,于是一次合并的贡献就是(g+now-h)*(g'+now-h')。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define _(A,B) ((A-1)*m+B)
using namespace std;
typedef long long ll;
const ll P=1000000007;
const int maxn=500010;
int n,m,H,tot;
ll ans;
int f[maxn],h[maxn];
ll g[maxn];
struct node
{
int x,y,v;
node() {}
node(int a,int b,int c) {x=a,y=b,v=c;}
}p[maxn<<1];
bool cmp(const node &a,const node &b)
{
return a.v<b.v;
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
int find(int x)
{
return (f[x]==x)?x:(f[x]=find(f[x]));
}
int main()
{
n=rd(),m=rd(),H=rd();
int i,j,a,b;
for(i=1;i<=n;i++) for(j=1;j<m;j++) p[++tot]=node(_(i,j),_(i,j+1),rd());
for(i=1;i<n;i++) for(j=1;j<=m;j++) p[++tot]=node(_(i,j),_(i+1,j),rd());
sort(p+1,p+tot+1,cmp);
for(i=1;i<=n*m;i++) f[i]=i,g[i]=1,h[i]=0;
for(i=1;i<=tot;i++)
{
a=p[i].x,b=p[i].y;
if(find(a)!=find(b))
{
g[f[b]]=(g[f[a]]+p[i].v-h[f[a]])*(g[f[b]]+p[i].v-h[f[b]])%P,h[f[b]]=p[i].v,f[f[a]]=f[b];
}
}
printf("%lld",(g[find(1)]+H-h[find(1)])%P);
return 0;
}

【BZOJ5101】[POI2018]Powód 并查集的更多相关文章

  1. BZOJ5101[POI2018]Powódź——并查集

    题目描述 在地面上有一个水箱,它的俯视图被划分成了n行m列个方格,相邻两个方格之间有一堵厚度可以忽略不计的墙,水 箱与外界之间有一堵高度无穷大的墙,因此水不可能漏到外面.已知水箱内每个格子的高度都是[ ...

  2. [bzoj5101][POI2018]Powódź_并查集

    Powódź bzoj-5101 POI-2018 题目大意:在地面上有一个水箱,它的俯视图被划分成了$n$行$m$列个方格,相邻两个方格之间有一堵厚度可以忽略不计的墙,水箱与外界之间有一堵高度无穷大 ...

  3. BZOJ5101 POI2018Powódź(并查集)

    如果某个格子的积水量超过了该格子的某个挡板高度,那么挡板另一端的积水量就会与其相同.看起来是一个不断合并的过程,考虑并查集.枚举深度,维护每个连通块内的方案数,深度超过某挡板高度时,将两端的连通块合并 ...

  4. BZOJ5101 : [POI2018]Powód

    求出Kruskal重构树,那么重构树上每个点的取值范围是定的. 考虑树形DP,则对于一个点,要么所有点水位相同,要么还未发生合并. 故$dp[x]=up[x]-down[x]+1+dp[l[x]]\t ...

  5. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

  6. 关押罪犯 and 食物链(并查集)

    题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨气值"( ...

  7. 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用

    图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...

  8. bzoj1854--并查集

    这题有一种神奇的并查集做法. 将每种属性作为一个点,每种装备作为一条边,则可以得到如下结论: 1.如果一个有n个点的连通块有n-1条边,则我们可以满足这个连通块的n-1个点. 2.如果一个有n个点的连 ...

  9. [bzoj3673][可持久化并查集 by zky] (rope(可持久化数组)+并查集=可持久化并查集)

    Description n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0& ...

随机推荐

  1. mpeg压缩输入格式---打包模式和平面模式

    版本 v1.0,存在内存问题在 void v4l2_process_image(struct buffer buf)中对 v4l2 采集来的一帧进行处理,存在 struct buffer buf 中b ...

  2. javascript中call、apply、argument、callee、caller

    1.Call方法 调用一个对象的一个方法,以另一个对象替换当前对象. call([thisObj[,arg1[, arg2[, [,.argN]]]]]) thisObj 可选项.将被用作当前对象的对 ...

  3. java动态代码的实现以及Class的卸载 (转至http://dustin.iteye.com/blog/46393)

    JavaWorld一篇题为 Add dynamic code to your application 的文章介绍了如何使用动态代理技术使普通的java源代码具有像jsp一样的动态编译效果,十分有趣.  ...

  4. Java设计模式(三) Visitor(訪问者)模式及多分派场景应用

    基本概念 Visitor 封装一些作用于数据结构中的各元素的操作,不同的操作能够借助新的visitor实现.减少了操作间的耦合性 訪问者能够将数据结构和对数据的操作解耦,使得添加对数据结构的操作不须要 ...

  5. par函数cex参数-控制文字和点的大小

    cex参数用来控制图片中点和文字的大小,对于一副图片来说,有很多的文字部分,包括x轴标签(xlab), y轴标签(ylab), x轴刻度上的文字, y轴刻度上的文字,主标题(main), 副标题(su ...

  6. 【Java面试题】54 去掉一个Vector集合中重复的元素

    在Java中去掉一个 Vector 集合中重复的元素 1)通过Vector.contains()方法判断是否包含该元素,如果没有包含就添加到新的集合当中,适用于数据较小的情况下. import jav ...

  7. ThinkPHP重写规则优化URL及Rewrite规则详细说明

    示例如下: http://www.topstack.cn/Article/detail/id/198.html 优化为 http://www.topstack.cn/article-198.html ...

  8. 怎样用MathType输入带分数

    MathType作为一种常用的数学公式编辑器.虽然其操作已经很简单了,但是对于刚刚接触MathType的新用户来说,一些最基本的MathType输入也是有一定难度的,一些人在MathType分数的编辑 ...

  9. VS2013+opencv2.4.9配置

    VS2013+opencv2.4.9(10)配置[zz] - yifeier12 - 博客园 http://www.cnblogs.com/cuteshongshong/p/4057193.html ...

  10. OpenCV学习:OpenCV源码编译(vc9)

    安装后的OpenCV程序下的build文件夹中,只找到了vc10.vc11和vc12三种编译版本的dll和lib文件,需要VS2010及以上的IDE版本,而没有我们常用的VS2008版本. 于是,需要 ...