bzoj 1798 维护序列seq 线段树

裸的线段树,注意标签下放就行了

多么痛的领悟,一定要开int64

 

/**************************************************************
    Problem: 1798
    User: BLADEVIL
    Language: Pascal
    Result: Accepted
    Time:24168 ms
    Memory:11948 kb
****************************************************************/
 
//By BLADEVIL
type
    rec                         =record
        left, right, sum        :int64;
        m_flag, p_flag          :int64;
    end;
 
var
    n, p, m                     :int64;
    t                           :array[0..300010] of rec;
 
procedure build(x,l,r:int64);
var
    mid                         :int64;
begin
    t[x].left:=l; t[x].right:=r;
    t[x].m_flag:=1;
    if l=r then
    begin
        read(t[x].sum);
        t[x].sum:=t[x].sum mod p;
        exit;
    end;
    with t[x] do mid:=(left+right) div 2;
    build(x*2,l,mid); build(x*2+1,mid+1,r);
    t[x].sum:=(t[x*2].sum+t[x*2+1].sum) mod p;
end;
     
procedure m_change(x,l,r,c:int64);
var
    mid                         :int64;
    cur                         :int64;
     
begin
    if t[x].left<>t[x].right then
    begin
        if t[x].m_flag<>1 then
        begin
            cur:=t[x].m_flag;
            t[2*x].m_flag:=(t[2*x].m_flag*cur) mod p;
            t[2*x].p_flag:=(t[2*x].p_flag*cur) mod p;
            t[2*x].sum:=(t[2*x].sum*cur) mod p;
            t[2*x+1].m_flag:=(t[2*x+1].m_flag*cur) mod p;
            t[2*x+1].p_flag:=(t[2*x+1].p_flag*cur) mod p;
            t[2*x+1].sum:=(t[2*x+1].sum*cur) mod p;
            t[x].m_flag:=1;
        end;
        if t[x].p_flag<>0 then
        begin
            cur:=t[x].p_flag;
            t[2*x].p_flag:=(t[2*x].p_flag+cur) mod p;
            t[2*x].sum:=(t[2*x].sum+cur*(t[2*x].right-t[2*x].left+1)) mod p;
            t[2*x+1].p_flag:=(t[2*x+1].p_flag+cur) mod p;
            t[2*x+1].sum:=(t[2*x+1].sum+cur*(t[2*x+1].right-t[2*x+1].left+1)) mod p;
            t[x].p_flag:=0;
        end;
    end;
    if (t[x].left=l) and (t[x].right=r) then
    begin
        t[x].sum:=(t[x].sum*c) mod p;
        t[x].p_flag:=(t[x].p_flag*c mod p);
        t[x].m_flag:=(t[x].m_flag*c mod p);
        exit;
    end;
    with t[x] do mid:=(left+right) div 2;
    if l>mid then m_change(x*2+1,l,r,c) else
    if r<=mid then m_change(x*2,l,r,c) else
    begin
        m_change(x*2,l,mid,c);
        m_change(x*2+1,mid+1,r,c);
    end;
    t[x].sum:=(t[2*x].sum+t[2*x+1].sum) mod p;
end;
 
procedure p_change(x,l,r,c:int64);
var
    mid                         :int64;
    cur                         :int64;
begin
    if t[x].left<>t[x].right then
    begin
        if t[x].m_flag<>1 then
        begin
            cur:=t[x].m_flag;
            t[2*x].m_flag:=(t[2*x].m_flag*cur) mod p;
            t[2*x].p_flag:=(t[2*x].p_flag*cur) mod p;
            t[2*x].sum:=(t[2*x].sum*cur) mod p;
            t[2*x+1].m_flag:=(t[2*x+1].m_flag*cur) mod p;
            t[2*x+1].p_flag:=(t[2*x+1].p_flag*cur) mod p;
            t[2*x+1].sum:=(t[2*x+1].sum*cur) mod p;
            t[x].m_flag:=1;
        end;
        if t[x].p_flag<>0 then
        begin
            cur:=t[x].p_flag;
            t[2*x].p_flag:=(t[2*x].p_flag+cur) mod p;
            t[2*x].sum:=(t[2*x].sum+cur*(t[2*x].right-t[2*x].left+1)) mod p;
            t[2*x+1].p_flag:=(t[2*x+1].p_flag+cur) mod p;
            t[2*x+1].sum:=(t[2*x+1].sum+cur*(t[2*x+1].right-t[2*x+1].left+1)) mod p;
            t[x].p_flag:=0;
        end;
    end;
    if (t[x].left=l) and (t[x].right=r) then
    begin
        t[x].sum:=(t[x].sum+c*(r-l+1)) mod p;
        t[x].p_flag:=(t[x].p_flag+c) mod p;
        exit;
    end;
    with t[x] do mid:=(left+right) div 2;
    if l>mid then p_change(x*2+1,l,r,c) else
    if r<=mid then p_change(x*2,l,r,c) else
    begin
        p_change(x*2,l,mid,c);
        p_change(x*2+1,mid+1,r,c);
    end;
    t[x].sum:=(t[x*2].sum+t[x*2+1].sum) mod p;
end;
 
function ask(x,l,r:int64):int64;
var
    mid                         :int64;
    cur                         :int64;
begin
    if t[x].left<>t[x].right then
    begin
        if t[x].m_flag<>1 then
        begin
            cur:=t[x].m_flag;
            t[2*x].m_flag:=(t[2*x].m_flag*cur) mod p;
            t[2*x].p_flag:=(t[2*x].p_flag*cur) mod p;
            t[2*x].sum:=(t[2*x].sum*cur) mod p;
            t[2*x+1].m_flag:=(t[2*x+1].m_flag*cur) mod p;
            t[2*x+1].p_flag:=(t[2*x+1].p_flag*cur) mod p;
            t[2*x+1].sum:=(t[2*x+1].sum*cur) mod p;
            t[x].m_flag:=1;
        end;
        if t[x].p_flag<>0 then
        begin
            cur:=t[x].p_flag;
            t[2*x].p_flag:=(t[2*x].p_flag+cur) mod p;
            t[2*x].sum:=(t[2*x].sum+cur*(t[2*x].right-t[2*x].left+1)) mod p;
            t[2*x+1].p_flag:=(t[2*x+1].p_flag+cur) mod p;
            t[2*x+1].sum:=(t[2*x+1].sum+cur*(t[2*x+1].right-t[2*x+1].left+1)) mod p;
            t[x].p_flag:=0;
        end;
    end;
    if (t[x].left=l) and (t[x].right=r) then
    begin
        ask:=t[x].sum mod p;
        exit;
    end;
    with t[x] do mid:=(left+right) div 2;
    if l>mid then ask:=ask(x*2+1,l,r) else
    if r<=mid then ask:=ask(x*2,l,r) else
    ask:=(ask(x*2,l,mid)+ask(x*2+1,mid+1,r)) mod p;
end;
     
procedure init;
begin
    read(n,p);
    build(1,1,n);
end;
 
procedure main;
var
    i                           :longint;
    k, l, r, x                  :int64;
     
begin
    read(m);
    for i:=1 to m do
    begin
        read(k);
        if k=1 then
        begin
            read(l,r,x);
            m_change(1,l,r,x);
        end else
        if k=2 then
        begin
            read(l,r,x);
            p_change(1,l,r,x);
        end else
        if k=3 then
        begin
            read(l,r);
            writeln(ask(1,l,r));
        end;
    end;
end;
 
begin
    init;
    main;
end.

 赠送对拍器

var
    n, m, p                    :longint;
    r, l                    :longint;
    i                        :longint;
    k                        :longint;
begin
    randomize;
    n:=100000;
    m:=100000;
    p:=random(1000000000)+1;
    writeln(n,' ',p);
    for i:=1 to n do write(random(1000000000)+1,' ');
    writeln;
    writeln(m);
    for i:=1 to m do 
    begin
        r:=random(n)+1;
        l:=random(r)+1;
        k:=random(3)+1;
        if k=3 then 
            writeln(k,' ',l,' ',r) else 
            writeln(k,' ',l,' ',r,' ',random(10000000000)+1);
    end;
end.

 

posted on 2013-12-11 08:36  BLADEVIL  阅读(381)  评论(1编辑  收藏  举报