zoukankan      html  css  js  c++  java
  • bzoj1789 AHOI 维护数列(线段树)

    首先想到线段树,然后刚开始写忽然想到树状数组求和岂不是更快,而且编程复杂度又小,于是把之前写的删掉,写树状数组,写完模版之后忽然发现这题竟然是区间修改!

    于是又删掉重写,忽然发现不会处理又加又乘的,果断看题解……

    经过几乎两个小时的调试,终于1A。

    需要注意的是,一定要让线段树的每一个区间保存的值时刻为正确的,这样才能在调用时直接返回。比如说这道题的change和query操作的最后一句话:

    sum:=f(g[k<<1]+g[k<<1+1])

    而不是

    sum:=f(t[k<<1].sum+t[k<<1+1].sum)

    时刻记住这点就ok了。一开始我还以为我的模版记错了呢……

    代码:

      1 type node=record
      2      l,r,ti,ad,sum:int64;
      3      end;
      4 var i,n,m,tagtime,tagadd,ch,x,y,c,p:longint;
      5     t:array[0..650000] of node;
      6 function f(x:int64):int64;
      7  begin
      8  f:=x mod p;
      9  end;
     10 function g(k:longint):longint;
     11  begin
     12  with t[k] do
     13   begin
     14   g:=f(f(sum*ti)+f(ad*(r-l+1)));
     15   end;
     16  end;
     17 procedure build(x,y,k:longint);
     18  var mid:longint;
     19  begin
     20  with t[k] do
     21   begin
     22   l:=x;r:=y;ad:=0;ti:=1;
     23   if l=r then begin read(sum);sum:=f(sum);exit;end;
     24   mid:=(l+r)>>1;
     25   build(l,mid,k<<1);
     26   build(mid+1,r,k<<1+1);
     27   sum:=f(t[k<<1].sum+t[k<<1+1].sum);
     28   end;
     29  end;
     30 procedure pushdown(k:longint);
     31  begin
     32  with t[k] do
     33   begin
     34   if ti<>1 then
     35    begin
     36    sum:=f(sum*ti);
     37    t[k<<1].ti:=f(t[k<<1].ti*ti);
     38    t[k<<1].ad:=f(t[k<<1].ad*ti);
     39    t[k<<1+1].ti:=f(t[k<<1+1].ti*ti);
     40    t[k<<1+1].ad:=f(t[k<<1+1].ad*ti);
     41    ti:=1;
     42    end;
     43   if ad<>0 then
     44    begin
     45    sum:=f(sum+ad*(r-l+1));
     46    t[k<<1].ad:=f(t[k<<1].ad+ad);
     47    t[k<<1+1].ad:=f(t[k<<1+1].ad+ad);
     48    ad:=0;
     49    end;
     50   end;
     51  end;
     52 procedure change(x,y,k:longint);
     53  var mid:longint;
     54  begin
     55  with t[k] do
     56   begin
     57   if (l=x) and (r=y) then
     58    begin
     59     ti:=(ti*tagtime) mod p;
     60     ad:=(ad*tagtime+tagadd) mod p;
     61     exit;
     62    end;
     63   pushdown(k);
     64   mid:=(l+r)>>1;
     65   if y<=mid then change(x,y,k<<1)
     66   else if x>mid then change(x,y,k<<1+1)
     67   else
     68    begin
     69    change(x,mid,k<<1);
     70    change(mid+1,y,k<<1+1);
     71    end;
     72   sum:=f(g(k<<1)+g(k<<1+1));
     73   end;
     74  end;
     75 function query(x,y,k:longint):longint;
     76  var mid:longint;
     77  begin
     78  with t[k] do
     79   begin
     80   pushdown(k);
     81   if (l=x) and (r=y) then exit(f(sum));
     82   mid:=(l+r)>>1;
     83   if y<=mid then query:=f(query(x,y,k<<1))
     84   else if x>mid then query:=f(query(x,y,k<<1+1))
     85   else query:=f(f(query(x,mid,k<<1))+f(query(mid+1,y,k<<1+1)));
     86   sum:=f(g(k<<1)+g(k<<1+1));
     87   end;
     88  end;
     89 procedure init;
     90  begin
     91  readln(n,p);
     92  build(1,n,1);
     93  end;
     94 procedure main;
     95  begin
     96  readln(m);
     97  for i:=1 to m do
     98   begin
     99    read(ch);
    100    if ch=1 then
    101     begin
    102     readln(x,y,tagtime);
    103     tagadd:=0;
    104     change(x,y,1);
    105     end
    106    else if ch=2 then
    107     begin
    108     readln(x,y,tagadd);
    109     tagtime:=1;
    110     change(x,y,1);
    111     end
    112    else
    113     begin
    114     readln(x,y);
    115     writeln(query(x,y,1));
    116     end;
    117   end;
    118  end;
    119 begin
    120  init;
    121  main;
    122 end.      
    View Code

    虽然现在已经12:30了,但我感觉,很开心。做了这道题,值!

  • 相关阅读:
    【解决办法】移动硬盘在电脑上显示“本地磁盘”并且出现打不开的情况
    在Windows上搭建Python环境
    Thymeleaf模板的使用
    thymeleaf中的th:remove用法
    AngularJS PhoneCat代码分析
    AngularJS PhoneCat代码分析
    利用java反射调用类的的私有方法--转
    Java Reflection (JAVA反射) --转载
    Eclipse 常用快捷键 (动画讲解)--转载
    三大JavaScript框架对比——AngularJS、BackboneJS和EmberJS
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/3773902.html
Copyright © 2011-2022 走看看