这题好难,翻了一下波兰文的题解……这好像是当年唯一没人A的题目
首先区间修改不难想到差分,我们令d1=x1,dn+1=-xn,di=xi-xi-1
注意Σdi=0,这样对于[l,r]的修改(比如+a) 就是d[l]+a d[r+1]-a
首先不难想到,对于每个di,ax+by=di一定要有解(gcd(a,b)|di)
这样我们知道这个方程的解为xi=x0+kb yi=y0-ka (x0,y0为这个方程一组解,可以由扩展欧几里德得到)
现在我们考虑最终的答案要求是Σxi=0 Σyi=0且(|Σxi|+|Σyi|)/2最小
我们有这样一个思路,先求出每个f(i)=|xi|+|yi|的最小值,最后总体贪心,调整成Σxi=0 Σyi=0
f(i)=|x0+kb|+|y0-ka|这显然是凸函数,我们可以用三分来解决
注意ax0+by0=di Σdi=0,所以我们只要Σki=0就满足Σxi=0 Σyi=0
设当前s=|Σki|,我们只要用堆调整s次即可得到满足条件的最优值
(关于s的规模不大会证,但跑得很快是了)
1 type node=record 2 loc:longint; 3 num:int64; 4 end; 5 6 var h:array[0..1000010] of node; 7 x,y:array[0..1000010] of int64; 8 d:array[0..1000010] of longint; 9 g,i,j,a,b,n,x0,y0:longint; 10 ans,l,m,r,s:int64; 11 12 procedure swap(var a,b:int64); 13 var c:int64; 14 begin 15 c:=a; 16 a:=b; 17 b:=c; 18 end; 19 20 function gcd(a,b:longint):longint; 21 begin 22 if b=0 then exit(a) 23 else exit(gcd(b,a mod b)); 24 end; 25 26 function cal(x,y,k:int64):int64; 27 begin 28 exit(abs(x+k*int64(b))+abs(y-k*int64(a))); 29 end; 30 31 procedure exgcd(a,b:longint; var x,y:longint); 32 var xx,yy:longint; 33 begin 34 if b=0 then 35 begin 36 x:=1; 37 y:=0; 38 end 39 else begin 40 exgcd(b,a mod b,x,y); 41 xx:=x; 42 yy:=y; 43 x:=yy; 44 y:=xx-a div b*yy; 45 end; 46 end; 47 48 procedure sift(i:longint); 49 var j:longint; 50 x:node; 51 begin 52 j:=i shl 1; 53 while j<=n do 54 begin 55 if (j<n) and (h[j].num>h[j+1].num) then inc(j); 56 if h[i].num>h[j].num then 57 begin 58 x:=h[i]; h[i]:=h[j]; h[j]:=x; 59 i:=j; 60 j:=j shl 1; 61 end 62 else break; 63 end; 64 end; 65 66 begin 67 readln(n,a,b); 68 g:=gcd(a,b); 69 for i:=1 to n do 70 begin 71 read(d[i]); 72 if d[i] mod g<>0 then 73 begin 74 writeln(-1); 75 halt; 76 end; 77 d[i]:=d[i] div g; 78 end; 79 a:=a div g; b:=b div g; 80 d[n+1]:=-d[n]; 81 for i:=n downto 2 do 82 d[i]:=d[i]-d[i-1]; 83 inc(n); 84 if a=b then 85 begin 86 for i:=1 to n do 87 ans:=ans+abs(d[i]); 88 writeln(ans div 2); 89 halt; 90 end; 91 exgcd(a,b,x0,y0); 92 for i:=1 to n do 93 begin 94 x[i]:=int64(x0)*int64(d[i]); 95 y[i]:=int64(y0)*int64(d[i]); 96 // writeln(x[i],' ',y[i],' ',d[i],':'); 97 l:=-d[i]; 98 r:=d[i]; 99 if l>r then swap(l,r); 100 while l+1<r do 101 begin 102 m:=(r-l+1) div 3; 103 if cal(x[i],y[i],l+m)>cal(x[i],y[i],l+2*m) then l:=l+m+1 104 else r:=l+2*m-1; 105 end; 106 if cal(x[i],y[i],l)>cal(x[i],y[i],r) then 107 begin 108 x[i]:=x[i]+r*int64(b); 109 y[i]:=y[i]-r*int64(a); 110 s:=s+r; 111 end 112 else begin 113 x[i]:=x[i]+l*int64(b); 114 y[i]:=y[i]-l*int64(a); 115 s:=s+l; 116 end; 117 // writeln(x[i],' ',y[i],' ',i,' ',d[i]); 118 end; 119 if s<0 then 120 begin 121 for i:=1 to n do 122 swap(x[i],y[i]); 123 g:=a; a:=b; b:=g; 124 s:=abs(s); 125 end; 126 for i:=1 to n do 127 begin 128 h[i].loc:=i; 129 h[i].num:=abs(x[i]-b)+abs(y[i]+a)-abs(x[i])-abs(y[i]); 130 end; 131 for i:=n div 2 downto 1 do 132 sift(i); 133 134 for i:=1 to s do 135 begin 136 j:=h[1].loc; 137 x[j]:=x[j]-b; 138 y[j]:=y[j]+a; 139 h[1].num:=abs(x[j]-b)+abs(y[j]+a)-abs(x[j])-abs(y[j]); 140 sift(1); 141 end; 142 for i:=1 to n do 143 ans:=ans+abs(x[i])+abs(y[i]); 144 writeln(ans div 2); 145 end.