P3373 【模板】线段树 2

传送门

一道板子题,思路和一基本没什么区别只是操作变了。话不多说上代码。

注意一下:这是大佬交给我们的指针写法,虽然不好理解但是比数组简洁方便容易错

声明:代码和HwH的线段树一样,因为是他帮我修改的。

 

#include<cstdio>

const int maxn=100005;
int p;
typedef long long int ll;

int n,q,m;
ll a[maxn];

struct Node
{
    ll tag1,tag2,v;
    int l,r;
    Node *ls,*rs;
    inline void maketag1(const ll w,const ll x)
    {
        v+=(r-l+1)%p*w%p;
        tag1=(tag1*x+w)%p;
    }
    inline void maketag2(const ll w)
    {
        v=v%p*w%p;
        tag2=tag2*w%p;
    }
    inline void pushup()
    {
        v=ls->v+rs->v;
        v%=p;
    }
    inline void pushdown()
    {
        if(tag1==0&&tag2==1) return;
        ls->maketag2(tag2);
        ls->maketag1(tag1,tag2);
        rs->maketag2(tag2);
        rs->maketag1(tag1,tag2);
        tag2=1,tag1=0;
    }
    Node(const int L,const int R)
    {
        l=L;r=R;
        if(l==r)
        {
            tag1=0;
            tag2=1;
            v=a[l]%p;
            ls=rs=NULL;
        }
        else
        {
            tag1=0;
            tag2=1;
            ll M=(L+R)>>1;
            ls=new Node(L,M);
            rs=new Node(M+1,R);
            pushup();
        }
    }
    
    inline bool InRange(const int L,const int R) {return (L<=l)&&(r<=R);}
    inline bool OutofRange(const int L,const int R) {return (l>R)||(r<L);}

    void upd1(const ll L,const ll R,const ll w)
    {
        if(InRange(L,R))
        {
            maketag1(w,1);
            return;
        }
        else if(!OutofRange(L,R))
        {
            pushdown();
            ls->upd1(L,R,w);
            rs->upd1(L,R,w);
            pushup();
        }
    }
    
    ll qry(const int L,const int R)
    {
        if(InRange(L,R)) return v%p;
        if(OutofRange(L,R)) return 0;
        pushdown();
        return (ls->qry(L,R)+rs->qry(L,R))%p;
    }
    
    void upd2(const int L,const int R,const ll w)
    {
        if(InRange(L,R))
        {
            maketag1(0,w);
            maketag2(w);
            return;
        }
        else if(!OutofRange(L,R))
        {
            pushdown();
            ls->upd2(L,R,w);
            rs->upd2(L,R,w);
            pushup();
        }
    }
};

int main()
{
    scanf("%d%d%d",&n,&q,&p);
    for(int i=1;i<=n;++i) scanf("%lld",a+i);
    Node *rot=new Node(1,n);
    for(ll o,x,y,z;q;--q)
    {
        scanf("%lld%lld%lld",&o,&x,&y);
        if(o==1)
        {
            scanf("%lld",&z);
            rot->upd2(x,y,z);
        }
        else if(o==2)
        {
            scanf("%lld",&z);
            rot->upd1(x,y,z);
        }
        else
        {
            printf("%lld\n",rot->qry(x,y));
        }
    }
    return 0;
}

 

 
posted @ 2020-07-06 09:49  国服混子瑶  阅读(119)  评论(0编辑  收藏  举报