清橙A1363. 水位 - 清华大学2012年信息学优秀高中学子夏令营


问题描述
  有一个正方形的地区,该地区特点鲜明:如果把它等分为N×N个小正方形格子的话,在每个格子内的任意地点的地表高度是相同的,并且是一个0到M之间的整数。正方形地区的外部被无限高的边界包围。
  该地区可能会有积水。经过多年的观察,人们发现了几个关于积水的重要规律:
  1. 每个格子要么完全没有积水,要么它内部的任意地点的水面高度都是相同的。并且水面高度一定大于地表高度。
  2. 每个格子的水面高度在0~M之间,并且一定是整数。
  3. 对于相邻(必须为边相邻)的两个格子,一定不会出现水自动从一个格子流向另一个格子的情况。也就是说,一定不能出现这两个格子都有水且水面高度不同,或者有水格子的水面比无水格子的地表要高的情况。
  例如,下面图中每个格子里有两个数a/b,说明该格子的地表高度是a,水面高度是b(均为海拔高度),而没有水的格子中b以“−”表示。则左边的情况是符合规律的,而右边的情况并不符合以上规律,因为水可以由2/4的格子流向3/−的格子。
清橙A1363. 水位 - 清华大学2012年信息学优秀高中学子夏令营_第1张图片
  (图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
对样例的说明
  符合规律的水位情况有以下六种 :

清橙A1363. 水位 - 清华大学2012年信息学优秀高中学子夏令营_第2张图片
数据规模和约定

清橙A1363. 水位 - 清华大学2012年信息学优秀高中学子夏令营_第3张图片
 
 
好一个并查集
首先我们正着想,一开始都有模模糊糊的这个想法,就是划分区域,这几个区域的水一旦高于分界线的高度就会汇合,所以先计算出水位低于分界线的方案数,再算高于分界线的方案数
显然,低于这个高度的方案数是这几个区域的方案数的乘积,高于这个高度的方案数就是最高限制-这个高度,这几个区域的方案数可以递归做
但是递归又难写,时间上也不允许
所以我们从小到大枚举分界线的高度,把这个格子四周的区域合并,一直到整个区域,用并查集维护区域的信息
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.
View Code

 

你可能感兴趣的:(2012)