题意:
分析:
- 暴力
随便来个数据结构直接模拟,但是操作量达到了 (1e7) 级别,也就是说单个操作必须做到 (O(1))
- 正解
观察发现只有全局操作和单点操作,所以用到了一个小 (trick) 就是维护一个全局标记,然后对于单点进行修改,这样可以做到 (O(1)) 进行全局修改,然后对于单点修改操作转化一下也可以做到 (O(1))
具体来说就是:
维护一个全局乘标记 (mul) 全局加标记 (add) 全局赋值标记 (tag) 全局和 (sum) 时间戳 (lst) 每一个点最近第一次单点赋值 (tim[])
这样每一个位置的值等价于 (v[x]*mul+add) ,然后我们开始分操作考虑怎么维护
- 单点赋值 (val)
我们逆向推出 (v[pos]) 应该变成什么 (v[pos]*mul+add=val o v[pos]=(val-add) imes inv(mul)) 然后直接修改 (v[pos]) 的值就好了
- 全局加 (val)
(add=add+val sum=sum+val*n)
- 全局乘 (val)
(add=add*val mul=mul*val sum=sum*val) 注意由于 (0) 没有逆元所以乘 (0) 的操作要看成全局赋值 (0)
- 全局赋值 (val)
(tag=val mul=1 add=0 sum=val*n) 同时更新一下 (lst)
- 单点查询
分情况讨论一下
(a) : 上一次全局修改在这一个点的单点赋值之前,也就是说全局赋值被覆盖了,那么 (ans=v[pos]*mul+add)
(b) : 上一次全局修改在单点修改之后,也就是说此时的值应该为全局赋值标记 (ans=tag*mul+add)
- 全局查询
直接上 (sum)
由于这题读入比较诡异,所以我们可以离散化出修改的点的坐标,这样就可以开的下 (v,tim)
tip:
诡异的读入要求 (a,b) 必须开成 (long long) 不然两个 (int) 相乘直接爆炸,不要问我怎么知道的/kk
代码:
#include<bits/stdc++.h>
using namespace std;
namespace zzc
{
long long read()
{
long long x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const int maxn = 1e5+5;
const long long mod = 1e7+19;
long long n,qt,cnt,t,lst,sum,ans,mul,add,tag;
long long d[maxn],tim[maxn],inv[mod+5],v[maxn];
struct query
{
long long opt,pos,val;
}q[maxn];
void init()
{
inv[1]=inv[0]=1;
for(int i=2;i<mod;i++) inv[i]=inv[mod%i]*(mod-mod/i)%mod;
n=read();qt=read();
for(int i=1;i<=qt;i++)
{
q[i].opt=read();
if(q[i].opt==1||q[i].opt==5) q[i].pos=read(),d[++cnt]=q[i].pos;
if(q[i].opt<=4) q[i].val=read(),q[i].val=(q[i].val%mod+mod)%mod;
if(q[i].opt==3&&q[i].val==0) q[i].opt=4;
}
sort(d+1,d+cnt+1);
cnt=unique(d+1,d+cnt+1)-d-1;
for(int i=1;i<=qt;i++) if(q[i].opt==1||q[i].opt==5) q[i].pos=lower_bound(d+1,d+cnt+1,q[i].pos)-d;
mul=1;tag=0;add=0;lst=0;
}
void work()
{
long long a,b,id;
init();
t=read();
for(int i=1;i<=t;i++)
{
a=read();b=read();
for(int j=1;j<=qt;j++)
{
id=(a+j*b)%qt+1;
if(q[id].opt==1)
{
if(tim[q[id].pos]<=lst) sum=(sum-(tag*mul%mod+add)%mod+mod)%mod;
else sum=(sum-(v[q[id].pos]*mul%mod+add)%mod+mod)%mod;
sum=(sum+q[id].val)%mod;
tim[q[id].pos]=(i-1)*qt+j;
v[q[id].pos]=(q[id].val-add+mod)%mod*inv[mul]%mod;
}
else if(q[id].opt==2)
{
add=(add+q[id].val)%mod;
sum=(sum+n*q[id].val%mod)%mod;
}
else if(q[id].opt==3)
{
add=add*q[id].val%mod;
mul=mul*q[id].val%mod;
sum=sum*q[id].val%mod;
}
else if(q[id].opt==4)
{
lst=(i-1)*qt+j;
tag=q[id].val;
mul=1;add=0;
sum=n*q[id].val%mod;
}
else if(q[id].opt==5)
{
if(tim[q[id].pos]<=lst) ans=(ans+(tag*mul%mod+add)%mod)%mod;
else ans=(ans+(v[q[id].pos]*mul%mod+add)%mod)%mod;
}
else if(q[id].opt==6)
{
ans=(ans+sum)%mod;
}
// printf("#%d: id=%d mul=%d add=%d tag=%d sum=%lld %lld
",(i-1)*qt+j,id,mul,add,tag,sum,ans);
}
}
printf("%lld
",ans%mod);
}
}
int main()
{
zzc::work();
return 0;
}