logo AlgoBeat OnlineJudge
登录 注册

题解

作者: _ZXY_  ·  发布于 2026-05-17 19:53:52  ·  最后修改于 2026-05-17 21:32:46
已通过
审核员:Shadow_T 管理员 · 2026-05-17 21:32:46

行询问,每行输入四个数字 ,以空格隔开。
,表示将位于 的之间的数字都加
,表示将位于 的之间的数字都乘
,表示询问 的值 忽略)。要输出非负的余数值
考虑如何处理区间乘。

某些群众:我们可以再打个懒标记 呀!

那如何处理区间求和呢?

在打乘法懒标记的时候,我们可以将原来的 懒标记同时乘上 。操作这段区间时下放一下就行了。

如何下放呢?
下放时我们优先下放 ,然后再下放

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+7,mod=10007;
#define int long long 
int a[N],id[N],mul[N],add[N],n,len;
void reset(int bid){//下放懒标记
    for(int i=(bid-1)*len+1;i<=min(bid*len,n);i++){
        a[i]=((1ll*a[i]*mul[bid])%mod+add[bid]+mod)%mod;
    }//先下放乘,然后加
    add[bid]=0;
    mul[bid]=1;
}
void Add(int opt,int l,int r,int c){
    c%=mod;
    if(id[l]==id[r]){
        reset(id[l]);
        for(int i=l;i<=r;i++){
            if(!opt)a[i]=((a[i]+c)%mod+mod)%mod;
            else a[i]=((1ll*a[i]*c%mod)+mod)%mod;
        }
        return;
    }
    reset(id[l]);
    reset(id[r]);
    for(int i=l;id[l]==id[i];i++){
        if(!opt)a[i]=((a[i]+c)%mod+mod)%mod;
        else a[i]=((1ll*a[i]*c%mod)+mod)%mod;
    }
    for(int i=id[l]+1;i<id[r];i++){
        if(!opt)add[i]=(add[i]+c)%mod;
        else mul[i]=mul[i]*1ll*c%mod,add[i]=add[i]*1ll*c%mod;
    }//add一起乘
    for(int i=r;id[i]==id[r];i--){
        if(!opt)a[i]=((a[i]+c)%mod+mod)%mod;
        else a[i]=((1ll*a[i]*c%mod)+mod)%mod;
    }
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    len=sqrt(n);
    for(int i=1;i<=n;i++){
        cin>>a[i];
        a[i]%=mod;
        id[i]=(i-1)/len+1;
    }
    for(int i=1;i<=n;i++)mul[i]=1;
    for(int i=1;i<=n;i++){
        int opt,l,r,c;
        cin>>opt>>l>>r>>c;
        if(opt<2)Add(opt,l,r,c);
        else{
            cout<<((a[r]*mul[id[r]]%mod+ add[id[r]])%mod+mod)%mod<<'\n';
        }
    }
}

暂无评论

登录 后即可评论。