问题描述
有一个正方形的地区,该地区特点鲜明:如果把它等分为N×N个小正方形格子的话,在每个格子内的任意地点的地表高度是相同的,并且是一个0到M之间的整数。正方形地区的外部被无限高的边界包围。
该地区可能会有积水。经过多年的观察,人们发现了几个关于积水的重要规律:
1.
每个格子要么完全没有积水,要么它内部的任意地点的水面高度都是相同的。并且水面高度一定大于地表高度。
2.
每个格子的水面高度在0~M之间,并且一定是整数。
3.
对于相邻(必须为边相邻)的两个格子,一定不会出现水自动从一个格子流向另一个格子的情况。也就是说,一定不能出现这两个格子都有水且水面高度不同,或者有水格子的水面比无水格子的地表要高的情况。
例如,下面图中每个格子里有两个数a/b,说明该格子的地表高度是a,水面高度是b(均为海拔高度),而没有水的格子中b以“?”表示。则左边的情况是符合规律的,而右边的情况并不符合以上规律,因为水可以由2/4的格子流向3/?的格子。
(图1)
该地区水文站的工作人员小A想知道,该地区中有多少种不同的水位情况符合规律。你能回答他的这个问题吗?
输入格式
输入文件的第一行包含两个正整数N和M。
随后的N行,每行包含N个非负整数。其中第i+1行的第j个数表示该地区第i行第j列格子的地表高度。
输出格式
输出文件只包含一个整数,即该地区符合规律的水位情况种数。
样例输入
4
3
1 1 1 1
1 2 2 2
1 2 3 3
1 2 3
2
样例输出
6
对样例的说明
符合规律的水位情况有以下六种 :
数据规模和约定
好一个并查集
首先我们正着想,一开始都有模模糊糊的这个想法,就是划分区域,这几个区域的水一旦高于分界线的高度就会汇合,所以先计算出水位低于分界线的方案数,再算高于分界线的方案数
显然,低于这个高度的方案数是这几个区域的方案数的乘积,高于这个高度的方案数就是最高限制-这个高度,这几个区域的方案数可以递归做
但是递归又难写,时间上也不允许
所以我们从小到大枚举分界线的高度,把这个格子四周的区域合并,一直到整个区域,用并查集维护区域的信息
WA了好多次,原因是高精度数空间没开够,囧......
1 const
2 maxn=103;
3 s=10000000;
4 fx:array[1..4]of longint=(1,0,-1,0);
5 fy:array[1..4]of longint=(0,1,0,-1);
6 type
7 point=record
8 x,y:longint;
9 end;
10 big=array[0..2000]of int64;
11 var
12 a:array[0..maxn,0..maxn]of longint;
13 b:array[0..maxn*maxn]of point;
14 f,h:array[0..maxn*maxn]of longint;
15 ans:array[0..maxn*maxn]of big;
16 n,m:longint;
17
18 operator *(var a,b:big)c:big;
19 var
20 i,j:longint;
21 begin
22 fillchar(c,sizeof(c),0);
23 for i:=1 to a[0] do
24 for j:=1 to b[0] do
25 inc(c[i+j-1],a[i]*b[j]);
26 c[0]:=a[0]+b[0]-1;
27 for i:=1 to c[0]-1 do
28 begin
29 inc(c[i+1],c[i]div s);
30 c[i]:=c[i]mod s;
31 end;
32 while c[c[0]]>=s do
33 begin
34 c[c[0]+1]:=c[c[0]]div s;
35 c[c[0]]:=c[c[0]]mod s;
36 inc(c[0]);
37 end;
38 end;
39
40 procedure add(var a:big;b:longint);
41 var
42 i:longint;
43 begin
44 inc(a[1],b);
45 i:=1;
46 while a[i]>=s do
47 begin
48 inc(a[i+1],a[i]div s);
49 a[i]:=a[i]mod s;
50 inc(i);
51 end;
52 if i>a[0] then a[0]:=i;
53 end;
54
55 function calc(i,j:longint):longint;
56 begin
57 exit((i-1)*n+j);
58 end;
59
60 function find(x:longint):longint;
61 begin
62 if f[x]=x then exit(x);
63 f[x]:=find(f[x]);
64 exit(f[x]);
65 end;
66
67 procedure swap(var x,y:point);
68 var
69 t:point;
70 begin
71 t:=x;x:=y;y:=t;
72 end;
73
74 procedure sort(l,r:longint);
75 var
76 i,j,y:longint;
77 begin
78 i:=l;
79 j:=r;
80 y:=a[b[(l+r)>>1].x,b[(l+r)>>1].y];
81 repeat
82 while a[b[i].x,b[i].y]<y do
83 inc(i);
84 while a[b[j].x,b[j].y]>y do
85 dec(j);
86 if i<=j then
87 begin
88 swap(b[i],b[j]);
89 inc(i);
90 dec(j);
91 end;
92 until i>j;
93 if i<r then sort(i,r);
94 if j>l then sort(l,j);
95 end;
96
97 procedure print(a:big);
98 var
99 i:longint;
100 k:int64;
101 begin
102 write(a[a[0]]);
103 for i:=a[0]-1 downto 1 do
104 begin
105 k:=s div 10;
106 while k>1 do
107 begin
108 if a[i]<k then write(0)
109 else break;
110 k:=k div 10;
111 end;
112 write(a[i]);
113 end;
114 end;
115
116 procedure main;
117 var
118 i,j,x,y:longint;
119 begin
120 read(n,m);
121 for i:=1 to n do
122 for j:=1 to n do
123 begin
124 read(a[i,j]);
125 h[calc(i,j)]:=a[i,j];
126 b[calc(i,j)].x:=i;
127 b[calc(i,j)].y:=j;
128 end;
129 sort(1,n*n);
130 for i:=1 to n*n do
131 begin
132 f[i]:=i;
133 ans[i][0]:=1;
134 ans[i][1]:=1;
135 end;
136 for i:=1 to n*n do
137 for j:=1 to 4 do
138 if (b[i].x+fx[j]>0) and (b[i].x+fx[j]<=n) and (b[i].y+fy[j]>0) and (b[i].y+fy[j]<=n) then
139 begin
140 x:=find(calc(b[i].x,b[i].y));
141 y:=find(calc(b[i].x+fx[j],b[i].y+fy[j]));
142 if (h[x]>=h[y]) and (x<>y) then
143 begin
144 add(ans[y],h[x]-h[y]);
145 ans[x]:=ans[x]*ans[y];
146 f[y]:=x;
147 end;
148 end;
149 add(ans[find(1)],m-a[b[n*n].x,b[n*n].y]);
150 print(ans[find(1)]);
151 end;
152
153 begin
154 main;
155 end.
清橙A1363. 水位 - 清华大学2012年信息学优秀高中学子夏令营,布布扣,bubuko.com