zoukankan      html  css  js  c++  java
  • bzoj2259

    这道题很不错,首先读入方式有一种跳跃的既视感:
    读入Si之后,我们可以直接往后跳Si,可以想到最短路,设序列为a[],我们设n+1是终点
    如果i+a[i]<=n+1 那么i-->i+a[i] 权值为0 否则i-->n+1 权值为i+a[i]-n
    注意这可以算是一种非常经典的区间建图的方法
    下面我们解决调整某个数,我们比划一下就知道,在相邻两点连一条权值为1的无向边即可
    然后我们可以跑最短路了
    但是看到n<=1000000是不是感觉dij+heap有点虚?实际上对这个图我们直接宽搜就好了
    为什么?仔细研究发现,大部分边权值不是1就是0,只有一些点到终点的权值是不和谐的
    但这有什么关系呢?我们到快到终点的那个点直接计算比较取最优即可

     1 const inf=1000000007;
     2 
     3 var q,f,d:array[0..1000010] of longint;
     4     ans,n,i,h,r:longint;
     5 
     6 function min(a,b:longint):longint;
     7   begin
     8     if a>b then exit(b) else exit(a);
     9   end;
    10 
    11 procedure add(x,w:longint);
    12   begin
    13     if (x<1) or (x>n+1) then exit;
    14     while d[x]>inf do
    15     begin
    16       d[x]:=w;
    17       inc(r);
    18       q[r]:=x;
    19       if f[x]>n then
    20       begin
    21         ans:=min(ans,f[x]-n-1+d[x]);
    22         exit;
    23       end;
    24       x:=f[x];
    25     end;
    26   end;
    27 
    28 procedure work;
    29   var x:longint;
    30   begin
    31     if f[1]>n then
    32     begin
    33       ans:=f[1]-n-1;
    34       exit;
    35     end;
    36     h:=1;
    37     add(f[1],0);
    38     while (h<=r) and (d[n+1]>inf) do
    39     begin
    40       x:=q[h];
    41       add(x-1,d[x]+1);
    42       add(x+1,d[x]+1);
    43       inc(h);
    44     end;
    45   end;
    46 
    47 begin
    48   readln(n);
    49   for i:=1 to n do
    50   begin
    51     read(f[i]);
    52     f[i]:=f[i]+i+1;
    53   end;
    54   ans:=inf;
    55   fillchar(d,sizeof(d),127);
    56   work;
    57   ans:=min(ans,d[n+1]);
    58   writeln(ans);
    59 end.
    View Code
  • 相关阅读:
    19 C#循环语句的跳过和中断 continue和break
    18 C#中的循环执行 for循环
    一种绝对提高开发水平的方法(推荐英语)
    大数据知识普及
    全链路压测压测报告
    QuickSearch快排
    二分查找
    算法
    基于领域驱动设计的业务中台架构设计
    【科普】Scrum——从橄榄球争球到敏捷开发
  • 原文地址:https://www.cnblogs.com/phile/p/4472951.html
Copyright © 2011-2022 走看看