zoukankan      html  css  js  c++  java
  • 【codevs2333】&【BZOJ2002】弹飞绵羊[HNOI2010](分块)

      我其实是在codevs上看到它的题号后才去做这道题的。。。2333。。。

      题目传送门:codevs:http://codevs.cn/problem/2333/  bzoj:http://www.lydsy.com/JudgeOnline/problem.php?id=2002

      题意已经说的很清晰了,蓝鹅……我不会做。

      看题解有两种写法:分块和link-cut tree。但是lct我不会,只能用分块了。

      但是怎么分块呢?

      我们想一下有什么暴力写法。一种是记录每个反弹装置能往后弹多长距离,这样效率是修改O(1)+查询O(n)。另一种是记录从每个反弹装置开始到被弹飞要被弹多少次,这样效率是修改O(n)+查询O(1)。我们可以想一个介于两者之间的做法,比如……把序列平均分成m块,记录每个反弹装置弹到下一个块要弹多少次 和 会弹到下一个块的哪一个装置。这样一来,效率就变成了修改O(n/m)+查询O(m),总时间复杂度就是O(n*(n/m+m))。显然,如果要使效率最快m就取√n。

      接下来就可以打代码+AC了。(代码真心很短)

    代码:

    var a,ne,x,y:array[0..200010]of longint;
      n,m,i,j,k,p,t,q,ans:longint;
    begin
      read(n); p:=trunc(sqrt(n));
      for i:=0 to n-1 do begin
        read(a[i]); ne[i]:=(i div p+1)*p;
      end;
      for i:=0 to n-1 do begin
        x[i]:=i; y[i]:=0;
        while(x[i]<ne[i])and(x[i]<n)do begin
          x[i]:=x[i]+a[x[i]]; inc(y[i]);
        end;
      end;
      read(m);
      for i:=1 to m do begin
        read(q);
        if q=1 then begin
          read(k); ans:=0;
          while k<n do begin
            ans:=ans+y[k]; k:=x[k];
          end;
          writeln(ans);
        end
        else begin
          read(k,t); a[k]:=t;
          for j:=ne[k]-1 downto ne[k]-p do
            if j+a[j]>=ne[j] then begin
              x[j]:=j+a[j]; y[j]:=1;
            end
            else begin
              x[j]:=x[j+a[j]]; y[j]:=y[j+a[j]]+1;
            end;
        end;
      end;
    end.
    弹飞绵羊

       lct等学了再补吧。。。

  • 相关阅读:
    linux下base命令
    lldpd-0.7.7代码解读(send_pdu部分)
    openwrt 包makefile
    字符
    AC_CONFIG_HEADER
    大小端
    查看使用了那种shell
    debia下安装libjpeg
    工作流模式 (zhuan)
    1.2.1 工作流管理系统参考模型 (zhuan)
  • 原文地址:https://www.cnblogs.com/quzhizhou/p/6756655.html
Copyright © 2011-2022 走看看