Luogu P3373 [Template] Segment Tree 2

This is a relatively simple line segment tree template question.

It is more to give an idea , the sequence problem when maintaining multiple operations that require Lazy Tag

For addition and query here, you can refer to interval addition template questions and Sol

Mainly when the mark is downloaded, pay attention to processing the multiplication first and then processing the addition

Why?

Because obviously multiplication has a higher priority than addition, if you add first and then multiply, it will explode

For example: 10+6*233

If the addition is calculated first, then it is 16*233, then it is obviously wrong

And even if this is the case such as (10+100)*233

You can also pass the multiplication mark to the addition first to become 10*233+100*233 ( the principle of the distributive law of multiplication , elementary school mathematics)

Then, after specifying the order, you can directly set the board of the line segment tree.

CODE

#include<cstdio>
using namespace std;
typedef long long LL;
const LL N=100005;
struct segtree
{
    LL sum,add,mul;
}tree[N<<2];
LL n,m,p,a[N],opt,x,y,z;
inline char tc(void)
{
    static char fl[100000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(LL &x)
{
    x=0; char ch=tc();
    while (ch<'0'||ch>'9') ch=tc();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
inline void write(LL x)
{
    if (x/10) write(x/10);
    putchar(x%10+'0');
}
inline void up(LL root)
{
    tree[root].sum=(tree[root<<1].sum+tree[root<<1|1].sum)%p;
}
inline void down(LL root,LL l,LL r)
{
    if (tree[root].add||tree[root].mul!=1)
    {
        tree[root<<1].mul=(tree[root<<1].mul*tree[root].mul)%p;
        tree[root<<1|1].mul=(tree[root<<1|1].mul*tree[root].mul)%p;
        tree[root<<1].add=(tree[root<<1].add*tree[root].mul)%p;
        tree[root<<1|1].add=(tree[root<<1|1].add*tree[root].mul)%p;
        tree[root<<1].sum=(tree[root<<1].sum*tree[root].mul)%p;
        tree[root<<1|1].sum=(tree[root<<1|1].sum*tree[root].mul)%p;
        tree[root].mul=1;
        tree[root<<1].add=(tree[root<<1].add+tree[root].add)%p;
        tree[root<<1|1].add=(tree[root<<1|1].add+tree[root].add)%p;
        tree[root<<1].sum=(tree[root<<1].sum+tree[root].add*l)%p;
        tree[root<<1|1].sum=(tree[root<<1|1].sum+tree[root].add*r)%p;
        tree[root].add=0;
    }
}
inline void build(LL root,LL l,LL r)
{
    tree[root].mul=1;
    if (l==r)
    {
        tree[root].sum=a[l];
        return;
    }
    LL mid=l+r>>1;
    build(root<<1,l,mid); build(root<<1|1,mid+1,r);
    up(root);
}
inline void modify_mul(LL root,LL l,LL r,LL beg,LL end,LL k)
{
    if (l>=beg&&r<=end)
    {
        tree[root].mul=(tree[root].mul*k)%p;
        tree[root].add=(tree[root].add*k)%p;
        tree[root].sum=(tree[root].sum*k)%p;
        return;
    }
    LL mid=l+r>>1;
    down(root,mid-l+1,r-mid);
    if (beg<=mid) modify_mul(root<<1,l,mid,beg,end,k);
    if (mid<end) modify_mul(root<<1|1,mid+1,r,beg,end,k);
    up(root);
}
inline void modify_add(LL root,LL l,LL r,LL beg,LL end,LL k)
{
    if (l>=beg&&r<=end)
    {
        tree[root].add=(tree[root].add+k)%p;
        tree[root].sum=(tree[root].sum+k*(r-l+1))%p;
        return;
    }
    LL mid=l+r>>1;
    down(root,mid-l+1,r-mid);
    if (beg<=mid) modify_add(root<<1,l,mid,beg,end,k);
    if (mid<end) modify_add(root<<1|1,mid+1,r,beg,end,k);
    up(root);
}
inline LL query(LL root,LL l,LL r,LL beg,LL end)
{
    if (l>=beg&&r<=end) return tree[root].sum;
    LL mid=l+r>>1,res=0;
    down(root,mid-l+1,r-mid);
    if (beg<=mid) res=(res+query(root<<1,l,mid,beg,end))%p;
    if (mid<end) res=(res+query(root<<1|1,mid+1,r,beg,end))%p;
    up(root);
    return res;
}
int main()
{
    //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    register LL i;
    read(n); read(m); read(p);
    for (i=1;i<=n;++i)
    read(a[i]);
    build(1,1,n);
    while (m--)
    {
        read(opt); read(x); read(y);
        if (opt==1) read(z),modify_mul(1,1,n,x,y,z%p);
        if (opt==2) read(z),modify_add(1,1,n,x,y,z%p);
        if (opt==3) write(query(1,1,n,x,y)),putchar('\n');
    }
    return 0;
}

this question and this questionbasically similarExactly the same, double the experience (but I played twice, the right should be proficient, after all, the line segment tree is really basic and important )

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325838972&siteId=291194637