#离线#洛谷 5358 [SDOI2019]快速查询
作者:互联网
分析
由于询问次数很多,只能离线去做,考虑全局的操作都可以打标记。
对于单点的操作,实际上的数为 \(x'=x*Mul+Add\) 由于这两个标记单独撤销比较困难,
不妨开一个数组直接维护 \(x=\frac{x'-Add}{Mul}\),
单点赋值就直接加上 \(\frac{x_q-x'}{Mul}\),单点查询再把标记乘回去即可,
注意当全局乘0时转换为全局赋值为0
代码
#include <cstdio>
#include <cctype>
#include <unordered_map>
#define rr register
using namespace std;
const int mod=10000019;
struct rec{int opt,x,y;}q[100011];
int inv[mod],Mul=1,w,Add,n,ans,Q;
unordered_map<int,int>tim;
inline signed iut(){
rr int ans=0,f=1; rr char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans*f;
}
inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline void doit(rec t){
switch (t.opt){
case 1:{
rr int now=mo(1ll*(tim.count(t.x)?tim[t.x]:0)*Mul%mod,Add);
w=mo(w,mod-now),tim[t.x]=1ll*mo(t.y,mod-Add)*inv[Mul]%mod,w=mo(w,t.y);
break;
}
case 2:{
Add=mo(Add,t.y),w=mo(w,1ll*n*t.y%mod);
break;
}
case 3:{
Mul=1ll*Mul*t.y%mod,Add=1ll*Add*t.y%mod,w=1ll*w*t.y%mod;
break;
}
case 4:{
Mul=1,Add=t.y,w=1ll*n*t.y%mod,tim.clear();
break;
}
case 5:{
ans=mo(mo(ans,Add),1ll*(tim.count(t.x)?tim[t.x]:0)*Mul%mod);
break;
}
case 6:{
ans=mo(ans,w);
break;
}
}
}
signed main(){
n=iut(),Q=iut(),inv[0]=inv[1]=1;
for (rr int i=2;i<mod;++i) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
for (rr int i=1;i<=Q;++i){
rr int opt=iut();
switch (opt){
case 1:{
q[i]=(rec){opt,iut(),iut()};
break;
}
case 2:{
q[i]=(rec){opt,0,iut()};
break;
}
case 3:{
q[i]=(rec){opt,0,iut()};
break;
}
case 4:{
q[i]=(rec){opt,0,iut()};
break;
}
case 5:{
q[i]=(rec){opt,iut(),0};
break;
}
case 6:{
q[i]=(rec){opt,0,0};
break;
}
}
if (opt==3&&!q[i].y) q[i].opt=4;
q[i].y=(q[i].y%mod+mod)%mod;
}
for (rr int T=iut();T;--T){
rr int x=iut(),y=iut();
for (rr int i=1;i<=Q;++i)
doit(q[(x+1ll*i*y)%Q+1]);
}
return !printf("%d",ans);
}
标签:洛谷,Mul,mo,离线,1ll,Add,ans,SDOI2019,mod 来源: https://www.cnblogs.com/Spare-No-Effort/p/15424162.html