题意:你要从(0,0)点走到(n,m), 每次只能往 x 轴或者 y 轴正方向移动一个单位距离。
从(i,j)移动到(i,j+1)的代价为 ri,从(i,j)移动到(i+1,j)的代价为 cj。
求最小代价。
对于 20%的数据, n, m<=5000。
对于 100%的数据, n, m<=10^5,0<ri,ci<=10^8。
思路:杜教原题
• 建出r和c的下凸壳,每次走斜率大的那个。
• 证明?
• P q
• | |
• a--|-----|---
• b--|-----|---
• ra(q-p)+cp(a-b)<=rb(q-p)+cq(a-b)
• (ra-rb)(q-p)<=(cq-cp)(a-b)
• (ra-rb)/(a-b)<=(cq-cp)/(q-p)<=.......(more columns and
rows.
• 斜率?
• 每次走过路径斜率递增--->下凸
• 如何证明在下凸壳上?
下凸壳显然 假设当前是第x1行第y1列,下一个行和列是x2和y2,那么考虑是先沿行走还是先沿列走
先沿行走:r[x1]*(y2-y1)+c[y2]*(x2-x1)
先沿列走:r[x2]*(y2-y1)+c[y1]*(x2-x1)
r[x1]*(y2-y1)+c[y2]*(x2-x1)<r[x2]*(y2-y1)+c[y1]*(x2-x1)
(r[x2]-r[x1])/(x2-x1)>(c[y2]-c[y1])/(y2-y1)
于是先沿斜率大的走
1 var x,y:array[0..200000,1..2]of longint; 2 q1,q2:array[0..200000]of longint; 3 r,c:array[0..200000]of int64; 4 n,m,i,j,l1,l2:longint; 5 k1,k2:double; 6 ans:int64; 7 8 function slope(i,j,k:longint):double; 9 begin 10 exit((y[i,k]-y[j,k])/(x[i,k]-x[j,k])); 11 end; 12 13 function clac(x1,y1,x2,y2,k:longint):int64; 14 begin 15 if k=1 then exit(r[x1]*(y2-y1)+c[y2]*(x2-x1)) 16 else exit(c[y1]*(x2-x1)+r[x2]*(y2-y1)); 17 end; 18 19 begin 20 assign(input,'masodik.in'); reset(input); 21 assign(output,'masodik.out'); rewrite(output); 22 readln(n,m); 23 for i:=0 to n do 24 begin 25 read(y[i,1]); x[i,1]:=i; r[i]:=y[i,1]; 26 end; 27 for i:=0 to m do 28 begin 29 read(y[i,2]); x[i,2]:=i; c[i]:=y[i,2]; 30 end; 31 for i:=0 to n do 32 begin 33 while (l1>1)and(slope(i,q1[l1],1)<=slope(q1[l1-1],q1[l1],1)) do dec(l1); 34 inc(l1); q1[l1]:=i; 35 end; 36 for i:=0 to m do 37 begin 38 while (l2>1)and(slope(i,q2[l2],2)<=slope(q2[l2-1],q2[l2],2)) do dec(l2); 39 inc(l2); q2[l2]:=i; 40 end; 41 i:=1; j:=1; 42 while (i<l1)and(j<l2) do 43 begin 44 k1:=slope(q1[i],q1[i+1],1); 45 k2:=slope(q2[j],q2[j+1],2); 46 if k1>k2 then 47 begin 48 ans:=ans+clac(q1[i],q2[j],q1[i],q2[j+1],1); 49 inc(j); 50 end 51 else 52 begin 53 ans:=ans+clac(q1[i],q2[j],q1[i+1],q2[j],2); 54 inc(i); 55 end; 56 end; 57 while i<l1 do 58 begin 59 ans:=ans+clac(q1[i],q2[l2],q1[i+1],q2[l2],1); 60 inc(i); 61 end; 62 while j<l2 do 63 begin 64 ans:=ans+clac(q1[l1],q2[j],q1[l1],q2[j+1],2); 65 inc(j); 66 end; 67 writeln(ans); 68 69 70 close(input); 71 close(output); 72 end.