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.

 

你可能感兴趣的:(线段树)