看到相邻格子都+1的操作一下就想到黑白染色了
相邻格子都+1说明不管怎么弄,黑格子的总和和白格子总和的差总是定值
这里首先要注意,最后不一定变成的是所有元素中的最大值,可能比它大
比如 1 2 2 
     2 1 0  这里最后可以全变成3
所以做题的时候下结论一定要小心,我们不妨设最后都变成了x,c1,c2表示黑白格子个数,s1,s2分别表示原来黑白格子元素和
则x*c1-s1=x*c2-s2
则(c1-c2)*x=s1-s2
如果棋盘格子数为奇数,则,最后一定变成(s1-s2)/(c1-c2),我们只要验证这个即可
否则,当s1≠s2则无解
等于的话就有许多解,随着x的增大显然操作次数增多,所以我们二分x判定
如何判定呢?
我们将s连黑点,白点连t,流量是x-初始值
对相邻黑白点连inf的边,表示这两个格子可以共同+1
最后我们只要判断是否满流即可

bzoj2756_二分bzoj2756_二分_02
  1 const inf=int64(1) shl 36;
  2       dx:array[1..4] of longint=(0,0,-1,1);
  3       dy:array[1..4] of longint=(1,-1,0,0);
  4 
  5 type node=record
  6        next,po:longint;
  7        flow:int64;
  8      end;
  9 
 10 var e:array[0..400010] of node;
 11     p,cur,pre,numh,h:array[0..1640] of longint;
 12     d:array[0..1640] of int64;
 13     num:array[0..40,0..40] of longint;
 14     a:array[0..40,0..40] of int64;
 15     test,t,i,n,m,j,k,len:longint;
 16     ans,mx,s1,s2,l,r,mid:int64;
 17 
 18 function min(a,b:int64):int64;
 19   begin
 20     if a>b then exit(b) else exit(a);
 21   end;
 22 
 23 procedure add(x,y:longint;f:int64);
 24   begin
 25     inc(len);
 26     e[len].po:=y;
 27     e[len].flow:=f;
 28     e[len].next:=p[x];
 29     p[x]:=len;
 30   end;
 31 
 32 procedure build(x,y:longint;f:int64);
 33   begin
 34     add(x,y,f);
 35     add(y,x,0);
 36   end;
 37 
 38 function sap:int64;
 39   var u,i,j,tmp,q:longint;
 40       neck:int64;
 41 
 42   begin
 43     fillchar(h,sizeof(h),0);
 44     fillchar(numh,sizeof(numh),0);
 45     for i:=0 to t do
 46       cur[i]:=p[i];
 47     neck:=inf;
 48     numh[0]:=t+1;
 49     u:=0;
 50     sap:=0;
 51     while h[0]<t+1 do
 52     begin
 53       d[u]:=neck;
 54       i:=cur[u];
 55       while i<>-1 do
 56       begin
 57         j:=e[i].po;
 58         if (e[i].flow>0) and (h[u]=h[j]+1) then
 59         begin
 60           neck:=min(neck,e[i].flow);
 61           cur[u]:=i;
 62           pre[j]:=u;
 63           u:=j;
 64           if u=t then
 65           begin
 66             sap:=sap+neck;
 67             while u<>0 do
 68             begin
 69               u:=pre[u];
 70               j:=cur[u];
 71               dec(e[j].flow,neck);
 72               inc(e[j xor 1].flow,neck);
 73             end;
 74             neck:=inf;
 75           end;
 76           break;
 77         end;
 78         i:=e[i].next;
 79       end;
 80       if i=-1 then
 81       begin
 82         dec(numh[h[u]]);
 83         if numh[h[u]]=0 then exit;
 84         q:=-1;
 85         tmp:=t;
 86         i:=p[u];
 87         while i<>-1 do
 88         begin
 89           j:=e[i].po;
 90           if (e[i].flow>0) and (h[j]<tmp) then
 91           begin
 92             tmp:=h[j];
 93             q:=i;
 94           end;
 95           i:=e[i].next;
 96         end;
 97         cur[u]:=q;
 98         h[u]:=tmp+1;
 99         inc(numh[h[u]]);
100         if u<>0 then
101         begin
102           u:=pre[u];
103           neck:=d[u];
104         end;
105       end;
106     end;
107   end;
108 
109 function check(w:int64):boolean;
110   var i,j,x,y:longint;
111       s:int64;
112   begin
113     len:=-1;
114     s:=0;
115     fillchar(p,sizeof(p),255);
116     for i:=1 to n do
117       for j:=1 to m do
118         if (i+j) mod 2=1 then build(num[i,j],t,w-a[i,j])
119         else begin
120           build(0,num[i,j],w-a[i,j]);
121           for k:=1 to 4 do
122           begin
123             x:=i+dx[k];
124             y:=j+dy[k];
125             if num[x,y]>0 then build(num[i,j],num[x,y],inf);
126           end;
127           s:=s+w-a[i,j];
128         end;
129 
130     if sap<>s then exit(false)
131     else begin
132       ans:=s;
133       exit(true);
134     end;
135   end;
136 
137 begin
138   readln(test);
139   while test>0 do
140   begin
141     dec(test);
142     readln(n,m);
143     fillchar(num,sizeof(num),0);
144     s1:=0;
145     s2:=0;
146     k:=0;
147     mx:=0;
148     for i:=1 to n do
149       for j:=1 to m do
150       begin
151         read(a[i,j]);
152         inc(k);
153         num[i,j]:=k;
154         if (i+j) mod 2=0 then s1:=s1+a[i,j]
155         else s2:=s2+a[i,j];
156         if a[i,j]>mx then mx:=a[i,j];
157       end;
158     t:=n*m+1;
159     ans:=-1;
160     if n*m mod 2=1 then
161     begin
162       if (mx<=s1-s2) and check(s1-s2) then writeln(ans)
163       else writeln(-1);
164     end
165     else begin
166       if s1<>s2 then writeln(-1)
167       else begin
168         l:=mx;
169         r:=int64(1) shl 33;
170         while l<=r do
171         begin
172           mid:=(l+r) shr 1;
173           if check(mid) then r:=mid-1
174           else l:=mid+1;
175         end;
176         writeln(ans);
177       end;
178     end;
179   end;
180 end.
181 
182  
View Code