题目大意
(n)个数,对这些数进行(t imes q)次操作,操作有单点修改、全局加、全局乘、全局修改、单点询问、全局求和这几种。
(t imes q)次操作中,每次操作都是来自于给出的(q)次基本操作之一。输出所有询问操作的和模(10^7+19)。
(nleq 10^9;qleq 10^5;tleq 100;-10^9leq 操作中涉及的值 leq 10^9)
题解
只用存(leq 10^5)个单点修改操作涉及的点。
正常的做法:维护全局加标记、乘标记、修改标记,单点修改时将这个点的值改为((值+加法逆元) imes 乘法逆元)。
并不对劲的做法:维护每个时刻的加标记、乘标记、修改标记、每个点上次修改的时刻,单点查询时,如果该点上次的修改操作是单点修改,值=((修改的数 imes 当前乘标记 imes修改时乘标记的逆元)+(当前加标记+修改时加标记的逆元 imes(当前乘标记 imes修改时乘标记的逆元)))。
预处理逆元。
代码
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
#define maxn 100007
#define maxx 10000027
#define maxm 10000007
#define LL long long
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void write(int x)
{
if(x==0){putchar('0'),putchar('
');return;}
int f=0;char ch[20];
if(x<0)putchar('-'),x=-x;
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('
');
return;
}
int t,a[maxn],b[maxn],n,q,pw[maxx],ny[maxx],mulmk[maxm],admk[maxm],lst[maxn],mkx[maxn],num[maxn],cntn,lstmk;
int qf[maxn],qx[maxn],qy[maxn],ans,nowsum;
const int mod=1e7+19;
int mul(int x,int y){int res=1;while(y){if(y&1)res=(LL)res*x%mod;x=(LL)x*x%mod,y>>=1;}return res;}
int getrk(int k)
{
int L=1,R=cntn,res=cntn+1;
while(L<=R)
{
int mid=(L+R)>>1;
if(num[mid]>=k)res=min(res,mid),R=mid-1;
else L=mid+1;
}
return res;
}
int mo(int x){if(x<0)return x+mod;return x>=mod?x-mod:x;}
int main()
{
pw[0]=1;rep(i,1,mod-1)pw[i]=(LL)pw[i-1]*i%mod;
ny[mod-1]=mul(pw[mod-1],mod-2);dwn(i,mod-2,0)ny[i]=(LL)ny[i+1]*(i+1)%mod;
rep(i,1,mod-1)ny[i]=(LL)ny[i]*pw[i-1]%mod;
n=read(),q=read();
rep(i,1,q)
{
qf[i]=read();
if(qf[i]==6)continue;
else if(qf[i]==1)qx[i]=read(),qy[i]=mo(read()%mod);
else qx[i]=read();
if(qf[i]==1)num[++cntn]=qx[i];
if(qf[i]==2||qf[i]==3||qf[i]==4)qx[i]=mo(qx[i]%mod);
}
t=read();
sort(num+1,num+cntn+1);
rep(i,1,t)a[i]=read(),b[i]=read();
rep(i,1,q)
{
if(qf[i]==1){qx[i]=getrk(qx[i]);}
else if(qf[i]==5){int qq=getrk(qx[i]);if(num[qq]==qx[i])qx[i]=qq;else qx[i]=-1;}
if(qf[i]==3&&qx[i]==0)qf[i]=4;
}
admk[0]=0,mulmk[0]=1;n%=mod;
rep(i,1,t)rep(j,1,q)
{
int p=((LL)a[i]+(LL)j*b[i])%q+1,pp=(i-1)*q+j;
if(qf[p]==1)
{
int val=0;admk[pp]=admk[pp-1],mulmk[pp]=mulmk[pp-1];
if(lstmk>=lst[qx[p]])val=admk[pp];
else val=mo((LL)mkx[qx[p]]*mulmk[pp]%mod*ny[mulmk[lst[qx[p]]]]%mod+mo(admk[pp]-(LL)admk[lst[qx[p]]]*mulmk[pp]%mod*ny[mulmk[lst[qx[p]]]]%mod));
nowsum=mo(nowsum+mo(qy[p]-val)),lst[qx[p]]=pp,mkx[qx[p]]=qy[p];
}
else if(qf[p]==2)
{
admk[pp]=mo(admk[pp-1]+qx[p]),mulmk[pp]=mulmk[pp-1];
nowsum=mo(nowsum+(LL)n*qx[p]%mod);
}
else if(qf[p]==3)
{
admk[pp]=(LL)admk[pp-1]*qx[p]%mod,mulmk[pp]=(LL)mulmk[pp-1]*qx[p]%mod;
nowsum=(LL)nowsum*qx[p]%mod;
}
else if(qf[p]==4)
{
lstmk=pp,admk[pp]=qx[p],mulmk[pp]=1;
nowsum=(LL)n*qx[p]%mod;
}
else if(qf[p]==5)
{
admk[pp]=admk[pp-1],mulmk[pp]=mulmk[pp-1];
if(qx[p]<0)ans=mo(ans+admk[pp]);
else
{
if(lstmk>=lst[qx[p]])ans=mo(ans+admk[pp]);
else ans=mo(ans+mo((LL)mkx[qx[p]]*mulmk[pp]%mod*ny[mulmk[lst[qx[p]]]]%mod+mo(admk[pp]-(LL)admk[lst[qx[p]]]*mulmk[pp]%mod*ny[mulmk[lst[qx[p]]]]%mod)));
}
}
else{
admk[pp]=admk[pp-1],mulmk[pp]=mulmk[pp-1];ans=mo(ans+nowsum);}
}
write(ans);
return 0;
}