关闭

bzoj 1798: [Ahoi2009]Seq 维护序列seq 双标记线段树

383人阅读 评论(0) 收藏 举报
分类:

题意:给出一个序列,有三个操作:每一段加上一个数或乘上一个数或输出这一段的和。


分析:一开始想不就是傻叉线段树吗,后来才发现没那么简单。

不过也只要维护一下运算顺序就好了。

一开始的pushlazy函数写的不优美,然后不知道为什么不停地WA,至今仍然没有找到原因。

后来看了别人的程序,把push操作改写了一下,也就是每个lazy标记都是已经被当前区间处理过的了,每一次push只要更改子区间的sum和lazy就好了。

看来代码风格优美一点还是很重要的!!!


代码:

const
  maxn=101000;
 
var
  t:array[1..maxn*10] of record
    l,r:longint;
    s,lazy1,lazy2:int64;
  end;
  n,tot:longint;
  p:int64;
  s:array[0..maxn] of int64;
 
procedure build(d,l,r:longint);
var
  m:longint;
begin
  if d>tot then tot:=d;
  t[d].l:=l;
  t[d].r:=r;
  t[d].s:=(s[r]-s[l-1]+p) mod p;
  t[d].lazy1:=1;
  t[d].lazy2:=0;
  if l=r then exit;
  m:=(l+r) div 2;
  build(d*2,l,m);
  build(d*2+1,m+1,r);
end;
 
procedure init;
var
  i:longint;
begin
  readln(n,p);
  for i:=1 to n do
  begin
    read(s[i]);
    s[i]:=(s[i-1]+s[i]) mod p;
  end;
  readln;
  build(1,1,n);
end;
 
procedure pushlazy(d:longint);
var
  x:longint;
begin
  if t[d].l=t[d].r then
  begin
    t[d].lazy1:=1;
    t[d].lazy2:=0;
    exit;
  end;
  t[d*2].s:=(t[d*2].s*t[d].lazy1+t[d].lazy2*(t[d*2].r-t[d*2].l+1)) mod p;
  t[d*2+1].s:=(t[d*2+1].s*t[d].lazy1+t[d].lazy2*(t[d*2+1].r-t[d*2+1].l+1)) mod p;
  t[d*2].lazy1:=t[d*2].lazy1*t[d].lazy1 mod p;
  t[d*2].lazy2:=(t[d*2].lazy2*t[d].lazy1+t[d].lazy2) mod p;
  t[d*2+1].lazy1:=t[d*2+1].lazy1*t[d].lazy1 mod p;
  t[d*2+1].lazy2:=(t[d*2+1].lazy2*t[d].lazy1+t[d].lazy2) mod p;
  t[d].lazy1:=1;
  t[d].lazy2:=0;
end;
 
procedure insert(d,l,r,k:longint;w:int64);
var
  m:longint;
begin
  pushlazy(d);
  if (t[d].l=l)and(t[d].r=r) then
  begin
    if k=1
      then begin
             t[d].s:=t[d].s*w mod p;
             t[d].lazy1:=t[d].lazy1*w mod p;
           end
      else begin
             t[d].s:=(t[d].s+(t[d].r-t[d].l+1)*w) mod p;
             t[d].lazy2:=(t[d].lazy2+w) mod p;
           end;
    exit;
  end;
  m:=(t[d].l+t[d].r) div 2;
  if r<=m
    then insert(d*2,l,r,k,w)
    else if l>m
           then insert(d*2+1,l,r,k,w)
           else begin
                  insert(d*2,l,m,k,w);
                  insert(d*2+1,m+1,r,k,w);
                end;
  t[d].s:=(t[d*2].s+t[d*2+1].s) mod p;
end;
 
function find(d,l,r:longint):int64;
var
  m:longint;
begin
  pushlazy(d);
  if (t[d].l=l)and(t[d].r=r) then exit(t[d].s mod p);
  m:=(t[d].l+t[d].r) div 2;
  if r<=m
    then exit(find(d*2,l,r))
    else if l>m
           then exit(find(d*2+1,l,r))
           else exit((find(d*2,l,m)+find(d*2+1,m+1,r)) mod p);
end;
 
procedure main;
var
  q,i,x,y,z,j:longint;
begin
  readln(q);
  for i:=1 to q do
  begin
    read(x);
    if x=1
      then begin
             readln(x,y,z);
             insert(1,x,y,1,z);
           end
      else if x=2
             then begin
                    readln(x,y,z);
                    insert(1,x,y,2,z);
                  end
             else begin
                    readln(x,y);
                    writeln(find(1,x,y));
                  end;
  end;
end;
 
begin
  init;
  main;
end.


0
1

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:128758次
    • 积分:9319
    • 等级:
    • 排名:第2024名
    • 原创:833篇
    • 转载:13篇
    • 译文:0篇
    • 评论:27条
    欢迎qq交流
    qq:763647200
    友情链接
    文章分类
    最新评论