传送门
做法:
记全体加法标记,全体乘法标记,数值总和 为 \(qa,qm,sum\),单个修改用 \(map\) 存。
操作一:将其数值赋为 \((x-qa)/qm\),修改 \(sum\)。(需预处理逆元)。
操作二:修改 \(qa\),\(sum\)。
操作三:修改 \(qa\),\(qm\),\(sum\)。
操作四:\(qa=x,qm=0\)。
操作五:找到 map 里的值乘上 qm 再加上 qa。
code:
#include<bits/stdc++.h>
#define ll long long
#define int long long
using namespace std;
const int N=5e5+8;
const ll mod=1e7+19;
int n,q,t;
ll a[100005][5];
map<int,ll> pp;
ll qa,qm;
ll sum;
ll ans=0;
ll inv[mod];
ll ck(int x)
{
if(pp.find(x)==pp.end()) return qa%mod;
else return (pp[x]*qm%mod+qa)%mod;
}
void work(int k)
{
if(a[k][0]==1) {
sum=(sum-ck(a[k][1])+mod)%mod;
pp[a[k][1]]=(a[k][2]-qa+mod)*inv[qm]%mod;
sum+=a[k][2];sum%=mod;
}
else if(a[k][0]==2) {
qa+=a[k][1];
qa%=mod;
sum+=(ll)n*a[k][1]%mod;
sum%=mod;
}
else if(a[k][0]==3){
qm=qm*a[k][1]%mod;
qa=qa*a[k][1]%mod;
sum=sum*a[k][1]%mod;
}
else if(a[k][0]==4){
sum=(ll)n*a[k][1]%mod;
qm=1,qa=a[k][1];
pp.clear();
}
else if(a[k][0]==5){
ans+=ck(a[k][1]);ans%=mod;
}
else ans+=sum,ans%=mod;
}
signed main()
{
inv[1]=1;
for(int i=2;i<mod;++i) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod; //线性预处理逆元
cin>>n;cin>>q;
for(int i=1;i<=q;i++)
{
scanf("%lld",&a[i][0]);
if(a[i][0]<6) scanf("%lld",&a[i][1]);
if(a[i][0]==1) scanf("%lld",&a[i][2]),a[i][2]=(a[i][2]%mod+mod)%mod;
else if(a[i][0]<=4) a[i][1]=(a[i][1]%mod+mod)%mod;
if(a[i][0]==3&&!a[i][1]) a[i][0]=4;
}
cin>>t;
while(t--)
{
ll a,b;
scanf("%lld%lld",&a,&b);
for(int i=1;i<=q;i++)
work((a+i*b)%q+1);
}
cout<<(ans%mod+mod)%mod<<endl;
}