真MnZn求调线段树
查看原帖
真MnZn求调线段树
453762
天下人间楼主2021/10/29 01:27

WA #1 #3 #4

#include <iostream>
#include <cstdio>
#include <queue>
#define int long long
using namespace std;

int tree[400001]={};
int tagc[400001]={};//乘积的tag
int tagh[400001]={};//和的tag
int nsum[400001]={};
int mo;

int left(int a)
{
    return a<<1;
}
int right(int a)
{
    return a<<1|1;
}
void push(int p)
{
    tree[p]=(tree[left(p)]+tree[right(p)])%mo;
}
//建树
void build(int p,int l,int r)
{
    if(r==l)
    {
        tree[p]=nsum[r]%mo;
        return;
    }
    int kkk=(r+l)>>1;
    build(left(p),l,kkk);
    build(right(p),kkk+1,r);
    push(p);
}
//下传,k1是父节点的和tag,k2是积tag
void f(int p,int l,int r,int k1,int k2)
{
    tree[p]=tree[p]*k2%mo+k1*(r-l+1)%mo;
    tree[p]%=mo;
    tagc[p]=tagc[p]*k2%mo;
    tagh[p]=tagh[p]*k2%mo+k1%mo;
    tagh[p]%=mo;
    tagc[p]%=mo;
}
void pushd(int p,int l,int r)
{
    int kkk=(l+r)>>1;
    f(left(p),l,kkk,tagh[p],tagc[p]);
    f(right(p),kkk+1,r,tagh[p],tagc[p]);
    tagh[p]=0;
    tagc[p]=1;
}
//乘
void update1(int ll,int rr,int p,int l,int r,int num)
{
    if(rr<l||ll>r)
        return;
    if(ll<=l&&rr>=r)
    {
        tree[p]*=num;
        tree[p]%=mo;
        tagc[p]*=num;
        tagc[p]%=mo;
        tagh[p]*=num;
        tagh[p]%=mo;
        return;
    }
    pushd(p,l,r);
    int kkk=(l+r)>>1;
    if(ll<=kkk)
        update1(ll,rr,left(p),l,kkk,num);
    if(rr>=kkk+1)
        update1(ll,rr,right(p),kkk+1,r,num);
    push(p);
    return;
}
//加
void update2(int ll,int rr,int p,int l,int r,int num)
{
    if(rr<l||ll>r)
        return;
    if(ll<=l&&rr>=r)
    {
        tree[p]+=num*(r-l+1)%mo;
        tree[p]%=mo;
        tagh[p]+=num;
        tagh[p]%=mo;
        return;
    }
    pushd(p,l,r);
    int kkk=(l+r)>>1;
    if(ll<=kkk)
        update2(ll,rr,left(p),l,kkk,num);
    if(rr>=kkk+1)
        update2(ll,rr,right(p),kkk+1,r,num);
    push(p);
    return;
}
//取结果
int ans(int ll,int rr,int l,int r,int p)
{

    if(rr<l||ll>r)
        return 0;
    int an=0;
    if(ll<=l&&rr>=r)
        return tree[p]%mo;
    int kkk=(l+r)>>1;
    pushd(p,l,r);
    if(ll<=kkk)
        an+=ans(ll,rr,l,kkk,left(p))%mo;
    if(rr>=kkk+1)
        an+=ans(ll,rr,kkk+1,r,right(p))%mo;
    return an%mo;
}
#undef int
int main()
{
    #define int long long
    int n,m;
    scanf("%lld %lld %lld",&n,&m,&mo);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&nsum[i]);
        tagc[i]=1;
        tagh[i]=0;
    }
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        int meiy;
        scanf("%lld",&meiy);
        if(meiy==1)
        {
            int aa,bb,cc;
            scanf("%lld %lld %lld",&aa,&bb,&cc);
            update1(aa,bb,1,1,n,cc);
        }
        if(meiy==2)
        {
            int aa,bb,cc;
            scanf("%lld %lld %lld",&aa,&bb,&cc);
            update2(aa,bb,1,1,n,cc);
        }
        if(meiy==3)
        {
            int aa,bb;
            scanf("%lld %lld",&aa,&bb);
            printf("%lld\n",ans(aa,bb,1,n,1)%mo);
        }
    }
    return 0;
}

2021/10/29 01:27
加载中...