zoukankan      html  css  js  c++  java
  • bzoj2792

    首先想到二分答案是吧,设为lim

    这道题难在判定,我们先不管将一个数变为0的条件

    先使序列满足相邻差<=lim,这个正着扫一遍反着扫一遍即可

    然后我们就要处理将一个数变为0的修改代价

    当i变为0后,我们分别考虑左右两边的代价,对于左边

    如果a[j]>(i-j)*lim的话,aj要变成a[i]+(i-j)*lim,否则的话,对于k<=j都不用变化,右边类似的道理

    观察式子,a[j]>(i-j)*lim即a[j]+j*lim>i*lim,怎么做很明显了吧……

      1 var a,b,d:array[0..1000010] of longint;
      2     c,v:array[0..1000010] of int64;
      3     l,r,mx,mid,ans,i,n:longint;
      4     m,s:int64;
      5 
      6 function min(a,b:longint):longint;
      7   begin
      8     if a>b then exit(b) else exit(a);
      9   end;
     10 
     11 function max(a,b:longint):longint;
     12   begin
     13     if a>b then exit(a) else exit(b);
     14   end;
     15 
     16 function check(lim:longint):longint;
     17   var y,i:longint;
     18       s,w,t:int64;
     19   begin
     20     for i:=1 to n do
     21       b[i]:=a[i];
     22     t:=0;
     23     for i:=1 to n-1 do
     24       if b[i+1]>b[i]+lim then
     25       begin
     26         t:=t+b[i+1]-(b[i]+lim);
     27         b[i+1]:=b[i]+lim;
     28       end;
     29     for i:=n downto 2 do
     30       if b[i-1]>b[i]+lim then
     31       begin
     32         t:=t+b[i-1]-(b[i]+lim);
     33         b[i-1]:=b[i]+lim;
     34       end;
     35     if t>m then exit(0);
     36     fillchar(c,sizeof(c),0);
     37     fillchar(d,sizeof(d),0);
     38     for i:=1 to n do
     39     begin
     40       y:=min(i+b[i] div lim,n);
     41       c[y]:=c[y]+b[i]-int64(y-i)*int64(lim);
     42       inc(d[y]);
     43       if i<>1 then c[i-1]:=c[i-1]-b[i];
     44       dec(d[i]);
     45     end;
     46     s:=0;
     47     w:=0;
     48     for i:=n downto 1 do
     49     begin
     50       s:=s+c[i]+w*int64(lim);
     51       v[i]:=s;
     52       w:=w+d[i];
     53     end;
     54     fillchar(c,sizeof(c),0);
     55     fillchar(d,sizeof(d),0);
     56     for i:=n downto 1 do
     57     begin
     58       y:=max(i-b[i] div lim,1);
     59       c[y]:=c[y]+b[i]-int64(i-y)*int64(lim);
     60       inc(d[y]);
     61       c[i]:=c[i]-b[i];
     62       if i<>1 then dec(d[i-1]);
     63     end;
     64     s:=0;
     65     w:=0;
     66     for i:=1 to n do
     67     begin
     68       s:=s+c[i]+w*int64(lim);
     69       v[i]:=v[i]+s;
     70       w:=w+d[i];
     71     end;
     72     for i:=1 to n do
     73       if t+v[i]<=m then exit(i);
     74 
     75     exit(0);
     76   end;
     77 
     78 begin
     79   readln(n,m);
     80   for i:=1 to n do
     81   begin
     82     read(a[i]);
     83     s:=s+a[i];
     84     if a[i]>mx then mx:=a[i];
     85   end;
     86   if s<=m then
     87   begin
     88     writeln('1 0');
     89     halt;
     90   end;
     91   l:=1;
     92   r:=mx;
     93   while l<=r do
     94   begin
     95     mid:=(l+r) shr 1;
     96     if check(mid)>0 then
     97     begin
     98       ans:=mid;
     99       r:=mid-1;
    100     end
    101     else l:=mid+1;
    102   end;
    103   writeln(check(ans),' ',ans);
    104 end.
    View Code
  • 相关阅读:
    NYOJ 38布线问题
    NYOJ 106背包问题
    基于贪心算法的几类区间覆盖问题 nyoj 12喷水装置(二) nyoj 14会场安排问题
    HDOJ 2546饭卡(01背包问题)
    FBI树-数据结构(二叉树)
    二叉树遍历(flist)(二叉树,已知中序层序,求先序)
    求先序排列(二叉树已知中序和后序,求先序)
    滑雪(dp)
    Python——plot可视化数据,作业8(python programming)
    数据库SQL语言学习----左外连接,右外连接,外连接,自然连接的形象对比
  • 原文地址:https://www.cnblogs.com/phile/p/4555813.html
Copyright © 2011-2022 走看看