• bzoj2800


    这题好难,翻了一下波兰文的题解……这好像是当年唯一没人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.
    View Code
  • 相关阅读:
    apache 问题 You don't have permission to access /test.php on this server 解决方法
    setTimeout和setInterval实现定时器的区别
    视图Ext.Viewport和窗口Ext.Window用法
    JavaScript设置Cookie
    布局Layout
    html中select标签刷新后不回到默认值而是保持之前选择值
    设置session失效的几种方法
    面板Ext.Panel使用
    树TreePanel
    让html元素随浏览器的大小自适应垂直居中
  • 原文地址:https://www.cnblogs.com/phile/p/4555777.html
Copyright © 2020-2023  润新知