记录编号 598454 评测结果 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
题目名称 [SYOI 2018] 简单的线段树 最终得分 100
用户昵称 Gravatar梦那边的美好ET 是否通过 通过
代码语言 C++ 运行时间 14.177 s
提交时间 2025-01-24 15:48:41 内存使用 5.91 MiB
显示代码纯文本
#include<bits/stdc++.h>
#define maxn 100010
#define ll long long
using namespace std;
int n,m,a1,a2,a3,s,a[maxn];
ll sum[maxn*4],lz1[maxn*4],lz2[maxn*4],mod;
void build(int p,int l,int r){
    lz1[p]=1;
    if(l==r)return;
    int mid=(l+r)/2;
    build(p*2,l,mid);build(p*2+1,mid+1,r);
    return;
}
void xc(int p,int l,int r){
    if(lz1[p]==1&&lz2[p]==0)return;
    int mid=(l+r)/2;
    //左子树
    sum[p*2]=sum[p*2]*lz1[p]%mod+lz2[p]*(ll)(mid-l+1)%mod;
    lz1[p*2]*=lz1[p],lz2[p*2]*=lz1[p];
    lz2[p*2]+=lz2[p];
    sum[p*2]%=mod;lz1[p*2]%=mod;lz2[p*2]%=mod;
    //右子树
    sum[p*2+1]=sum[p*2+1]*lz1[p]%mod+lz2[p]*(ll)(r-mid)%mod;
    lz1[p*2+1]*=lz1[p],lz2[p*2+1]*=lz1[p];
    lz2[p*2+1]+=lz2[p];
    sum[p*2+1]%=mod;lz1[p*2+1]%=mod;lz2[p*2+1]%=mod;
    lz1[p]=1,lz2[p]=0;
    return;
}
void insert1(int p,int l,int r,int l1,int r1){//区间加
    if(l==l1&&r1==r){
        sum[p]+=(ll)(r-l+1)*(ll)a3;sum[p]%=mod;
        lz2[p]+=(ll)a3;lz2[p]%=mod;
        return;
    }
    xc(p,l,r);
    int mid=(l+r)/2;
    if(r1<=mid)insert1(p*2,l,mid,l1,r1);
    else if(mid<l1)insert1(p*2+1,mid+1,r,l1,r1);
    else insert1(p*2,l,mid,l1,mid),insert1(p*2+1,mid+1,r,mid+1,r1);
    sum[p]=sum[p*2]+sum[p*2+1];sum[p]%=mod;
    return;
}
void insert2(int p,int l,int r,int l1,int r1){//区间乘
    if(l==l1&&r1==r){
        sum[p]*=(ll)a3;sum[p]%=mod;
        lz1[p]*=(ll)a3;lz1[p]%=mod;
        lz2[p]*=(ll)a3;lz2[p]%=mod;
        return;
    }
    xc(p,l,r);
    int mid=(l+r)/2;
    if(r1<=mid)insert2(p*2,l,mid,l1,r1);
    else if(mid<l1)insert2(p*2+1,mid+1,r,l1,r1);
    else insert2(p*2,l,mid,l1,mid),insert2(p*2+1,mid+1,r,mid+1,r1);
    sum[p]=sum[p*2]+sum[p*2+1];sum[p]%=mod;
    return;
}
ll getsum(int p,int l,int r,int l1,int r1){
    if(l==l1&&r==r1)return sum[p];
    xc(p,l,r);
    int mid=(l+r)/(ll)2;
    if(r1<=mid)return getsum(p*2,l,mid,l1,r1);
    if(mid<l1)return getsum(p*2+1,mid+1,r,l1,r1);
    return (getsum(p*2,l,mid,l1,mid)+getsum(p*2+1,mid+1,r,mid+1,r1))%mod;
}
int main(){
    freopen("easilysegmenttree.in","r",stdin);
    freopen("easilysegmenttree.out","w",stdout);
    scanf("%d%d%lld",&n,&m,&mod);
    build(1,1,n);
    while(m--){
        scanf("%d%d%d",&s,&a1,&a2);
        if(s==1){
            scanf("%d",&a3);
            insert1(1,1,n,a1,a2);
        }
        if(s==2){
            scanf("%d",&a3);
            insert2(1,1,n,a1,a2);
        }
        if(s==3)printf("%lld\n",(getsum(1,1,n,a1,a2)%mod+mod)%mod);
    }
    return 0;
}