zoukankan      html  css  js  c++  java
  • BZOJ5101 POI2018Powódź(并查集)

      如果某个格子的积水量超过了该格子的某个挡板高度,那么挡板另一端的积水量就会与其相同。看起来是一个不断合并的过程,考虑并查集。枚举深度,维护每个连通块内的方案数,深度超过某挡板高度时,将两端的连通块合并,即方案数相乘。再加上该连通块均为当前深度的这种方案。这样复杂度即为O(nmHα)或O(n2m2α)。

      注意到每次更新所有连通块的答案并没有意义,于是可以进一步优化,对每个连通块存储其已被更新到的深度,需要将其合并时再实际更新。复杂度即为O(nmα)。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 1000010
    #define P 1000000007
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,m,h,fa[N],ans[N],cur[N],t;
    struct data
    {
        int x,y,z;
        bool operator <(const data&a) const
        {
            return z<a.z;
        }
    }edge[N];
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    int trans(int x,int y){return (x-1)*m+y;}
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj5101.in","r",stdin);
        freopen("bzoj5101.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read(),h=read();
        for (int i=1;i<=n*m;i++) fa[i]=i,ans[i]=1;
        for (int i=1;i<=n;i++) 
            for (int j=1;j<m;j++)
            t++,edge[t].x=trans(i,j),edge[t].y=trans(i,j+1),edge[t].z=read();
        for (int i=1;i<n;i++)
            for (int j=1;j<=m;j++)
            t++,edge[t].x=trans(i,j),edge[t].y=trans(i+1,j),edge[t].z=read();
        sort(edge+1,edge+t+1);
        for (int i=1;i<=t;i++)
        {
            int p=find(edge[i].x),q=find(edge[i].y);
            if (p!=q)
            {
                ans[p]+=edge[i].z-cur[p];
                ans[q]+=edge[i].z-cur[q];
                fa[q]=p;ans[p]=1ll*ans[p]*ans[q]%P;cur[p]=edge[i].z;
            }
        }
        cout<<(ans[find(1)]+h-cur[find(1)])%P;
        return 0;
    }
  • 相关阅读:
    双循环建表____1911年 为 辛亥年
    技巧方法
    sscanf
    02-02环境准备-pyenv与virtualenv以及venv方案对比
    02-01环境准备-virtualenv和venv
    02-01环境准备-pyenv
    【转】解决weblogic启动慢和创建域慢的方法
    chrome新版打开新标签页自动打开谷歌主页
    centos6分辨率设置
    12-openldap使用AD密码
  • 原文地址:https://www.cnblogs.com/Gloid/p/10076252.html
Copyright © 2011-2022 走看看