关闭

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

492人阅读 评论(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
查看评论

BZOJ 1798 [Ahoi2009]Seq 维护序列seq

线段树
  • Orion_Rigel
  • Orion_Rigel
  • 2016-07-10 21:22
  • 201

[BZOJ]1798: [Ahoi2009]Seq 维护序列seq

An easy problem Chttp://www.lydsy.com/JudgeOnline/problem.php?id=1798 http://acm.uestc.edu.cn/#/problem/show/1597Time Limit: 4000/2000MS (Java/Others...
  • ctsas
  • ctsas
  • 2017-07-31 11:51
  • 114

1798: [Ahoi2009]Seq 维护序列seq 线段树

注意标记的优先级问题。#include<iostream> #include<cstdio> #define ll long long #define N 100005 using namespace std; int n,m,P; int a[N]; int l[N<...
  • Phenix_2015
  • Phenix_2015
  • 2016-02-25 09:18
  • 224

BZOJ 1798: [Ahoi2009]Seq 维护序列seq

题目地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1798 题目大意:维护一个序列,提供区间加、区间乘、区间询问操作。 算法讨论:         线段树模板题。     &#...
  • u013703661
  • u013703661
  • 2014-02-19 13:29
  • 882

[BZOJ 1798][Ahoi2009]Seq 维护序列seq

先乘后加线段树
  • Horizon_SMZ
  • Horizon_SMZ
  • 2016-03-17 16:59
  • 272

【BZOJ】1798 [Ahoi2009]Seq 维护序列seq

【BZOJ】1798 [Ahoi2009]Seq 维护序列seq Description老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。 有长为N的数列,不妨设为a1,a2,…,aNa。有如下三种操作形式: (1)把数列中的一段数全部乘一个值;
  • Pure_W
  • Pure_W
  • 2016-10-26 19:02
  • 174

bzoj 1798: [Ahoi2009]Seq 维护序列seq

Description 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。 有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数...
  • lqybzx
  • lqybzx
  • 2015-02-06 20:29
  • 660

bzoj 1798 [Ahoi2009]Seq 维护序列seq

线段树区间更新
  • u012077152
  • u012077152
  • 2015-05-25 21:25
  • 210

【BZOJ 1798】[Ahoi2009]Seq 维护序列seq

乘法和加法可以都保留 加个小处理! #include #include #include #define MAXN 100000 #define LL long long LL a[MAXN*4],c[MAXN*4],j[MAXN*4],num[MAXN*4]; LL n,p,m; void ...
  • sxb_201
  • sxb_201
  • 2016-03-10 19:01
  • 86

【BZOJ 1798】 [Ahoi2009]Seq 维护序列seq

双标记线段树~
  • Regina8023
  • Regina8023
  • 2015-03-09 19:17
  • 905
    个人资料
    • 访问:234177次
    • 积分:10686
    • 等级:
    • 排名:第1861名
    • 原创:911篇
    • 转载:3篇
    • 译文:0篇
    • 评论:42条
    欢迎qq交流
    qq:763647200
    文章分类
    最新评论