[bzoj5101][並查集]Powódź
阿新 • • 發佈:2018-12-12
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,表示(i,j)和(i,j+1)之間的牆的高度。 接下來n-1行,每行m個整數b[i]j
,表示(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種情況。
題解
把牆按高度排序 設sum[i]表示i這個連通塊在上一次訪問到他的時候的水位及以下的方案數 掃到一堵牆的時候 如果這兩個連通塊沒有連在一起 顯然水位到這堵牆的高度時候他們就會連在一起了 設上一次訪問到這兩個連通塊的水位分別是h1,h2 這堵牆的高度是H 這兩個連通塊並起來的答案就是 然後就沒了…
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<vector> #include<ctime> #define LL long long #define mp(x,y) make_pair(x,y) #define mod 1000000007 using namespace std; const int dx[3]={0,0,1}; const int dy[3]={0,1,0}; inline int read() { int f=1,x=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void write(int x) { if(x<0)putchar('-'),x=-x; if(x>9)write(x/10); putchar(x%10+'0'); } inline void print(int x){write(x);printf(" ");} int n,m,H; struct Nod{int h,x,y,op;}w[1110000];int t1; bool cmp(Nod n1,Nod n2){return n1.h<n2.h;} int pt(int x,int y){return (x-1)*m+y;} int fa[510000],lasth[510000];LL sum[510000]; int findfa(int x){return fa[x]==x?fa[x]:fa[x]=findfa(fa[x]);} int main() { // freopen("a.in","r",stdin); // freopen("a.out","w",stdout); n=read();m=read();H=read(); for(int i=1;i<=n;i++) for(int j=1;j<m;j++)w[++t1].h=read(),w[t1].x=i,w[t1].y=j,w[t1].op=1; for(int i=1;i<n;i++) for(int j=1;j<=m;j++)w[++t1].h=read(),w[t1].x=i,w[t1].y=j,w[t1].op=2; sort(w+1,w+1+t1,cmp); for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)fa[pt(i,j)]=pt(i,j),sum[pt(i,j)]=1; int cnt=n*m,last=t1; for(int i=1;i<=t1;i++) { int u=w[i].x,v=w[i].y; int x=w[i].x+dx[w[i].op],y=w[i].y+dy[w[i].op]; int u1=pt(u,v),u2=pt(x,y); int p=findfa(u1),q=findfa(u2); if(p!=q) { LL g1=sum[p],g2=sum[q]; sum[q]=((w[i].h-lasth[p]+g1)*(w[i].h-lasth[q]+g2)%mod); lasth[q]=w[i].h;fa[p]=q;cnt--; } if(cnt==1){last=i;break;} } printf("%lld\n",(sum[findfa(pt(1,1))]+H-w[last].h)%mod); return 0; }