传送门
SOL
输入有点复杂,仔细读完后发现不同的操作最多只有
1
e
5
1e5
1e5种,离散化线段树算出来都
2
e
8
2e8
2e8,更不要说大常数,
T
L
E
TLE
TLE是无疑的。(好像有人用平衡树
A
A
A了?)
分析发现除了单点赋值,查值,其余都是全体的操作,可以
O
(
1
)
O(1)
O(1)做。
对于赋值,有
(
(
x
+
b
1
)
∗
a
1
+
b
2
)
∗
a
2
.
.
.
=
x
∗
a
1
∗
a
2
∗
.
.
.
+
K
,
K
与
x
无
关
((x+b_1)*a_1+b_2)*a_2...=x*a_1*a_2*...+K,K与x无关
((x+b1)∗a1+b2)∗a2...=x∗a1∗a2∗...+K,K与x无关
维护一个
s
t
d
std
std,标准值,
n
o
w
=
s
t
d
−
(
l
a
s
s
t
d
−
l
a
s
n
o
w
)
∗
a
1
∗
a
2
∗
.
.
.
now=std-(lasstd-lasnow)*a_1*a_2*...
now=std−(lasstd−lasnow)∗a1∗a2∗...;
维护前缀乘积和前缀乘积的逆元就行了(离线维护 1 e 5 1e5 1e5个数值的逆元)
注意乘0和全体赋值相当于清空,要特殊讨论。
CODE
#include<bits/stdc++.h>
using namespace std;
#define sf scanf
#define ll long long
#define cs const
#define ri register int
#define gc getchar()
#define in red()
inline int red(){
int num=0,f=1;char c=gc;
for(;!isdigit(c);c=gc)if(c=='-')f=-1;
for(;isdigit(c);c=gc)num=num*10+(c^48);
return num*f;
}
cs int mod=1e7+19,N=1e5+10,M=1e7+10;
inline int mul(cs int &a,cs int &b){return 1ll*a*b%mod;}
inline void check(int &a){a%=mod;a= a<0 ? a+mod : a;}
inline int add(cs int &a,cs int &b){return a+b>mod? a-mod+b : a+b;}
inline int dec(cs int &a,cs int &b){return a-b<0 ? a+mod-b :a-b;}
inline int ksm(int a,int b){a%=mod;int ans=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ans=mul(ans,a);return ans;}
map<int,int> f,pos;
typedef pair<int,int>pi;
#define fi first
#define se second
struct node{
int op,id,vl;
}q[N];
int fc[M],ifc[M],rf[N],rnum[N],seq[M];
int n,las0,lasvl,ans,cnt1,cnt2,sum,st,tot,t,Q,up;
pi las[N],ab[N];
inline void update(int i){
if(las[i].se<las0||las[i].se<lasvl)las[i].fi=0;
}
inline int query(int i,int tim){
return add(st,mul(las[i].fi,fc[tim]));
}
signed main(){
// freopen("data.in","r",stdin);
// freopen("rhj.out","w",stdout);
n=in;
Q=in;
for(ri i=1;i<=Q;++i){
q[i].op=in;
if(q[i].op==1){
q[i].id=in,q[i].vl=in;check(q[i].vl);
if(!pos[q[i].id])pos[q[i].id]=++cnt1;
q[i].id=pos[q[i].id];
if(!f[q[i].vl])f[q[i].vl]=++cnt2,rf[cnt2]=q[i].vl,rnum[cnt2]=ksm(q[i].vl,mod-2);
q[i].vl=f[q[i].vl];
}
if(q[i].op==2||q[i].op==3||q[i].op==4){
q[i].vl=in;check(q[i].vl);
if(!f[q[i].vl])f[q[i].vl]=++cnt2,rf[cnt2]=q[i].vl,rnum[cnt2]=ksm(q[i].vl,mod-2);
q[i].vl=f[q[i].vl];
}
if(q[i].op==5){
q[i].id=in;
if(!pos[q[i].id])pos[q[i].id]=++cnt1;
q[i].id=pos[q[i].id];
}
}
t=in;
for(ri i=1;i<=t;++i)ab[i].fi=in,ab[i].se=in,ab[i].fi%=Q,ab[i].se%=Q;
up=t*Q;
for(ri i=1;i<=up;++i){
int jj=i/Q,j=i-jj*Q;++jj;if(!j)j=Q,--jj;
seq[i]=(1ll*ab[jj].fi%Q+1ll*ab[jj].se*j%Q)%Q+1;
}
fc[0]=ifc[0]=1;n%=mod;
for(ri tim=1;tim<=up;++tim){
int i=seq[tim];
ifc[tim]=ifc[tim-1];fc[tim]=fc[tim-1];
if(q[i].op==1){
update(q[i].id);
int now=query(q[i].id,tim);
sum=dec(sum,now);
sum=add(sum,rf[q[i].vl]);
las[q[i].id].se=tim;
las[q[i].id].fi=mul(dec(rf[q[i].vl],st),ifc[tim]);
}
if(q[i].op==2){
st=add(st,rf[q[i].vl]);
sum=add(sum,mul(n,rf[q[i].vl]));
}
if(q[i].op==3){
if(rf[q[i].vl]==0){
las0=tim;lasvl=0;sum=0;
st=0;
fc[tim]=1;ifc[tim]=1;
}
else{
st=mul(st,rf[q[i].vl]);
fc[tim]=mul(fc[tim],rf[q[i].vl]);
ifc[tim]=mul(ifc[tim],rnum[q[i].vl]);
sum=mul(sum,rf[q[i].vl]);
}
}
if(q[i].op==4){
las0=0;lasvl=tim;sum=mul(n,rf[q[i].vl]);
fc[tim]=1;ifc[tim]=1;
st=rf[q[i].vl];
}
if(q[i].op==5){
update(q[i].id);
ans=add(ans,query(q[i].id,tim));
}
if(q[i].op==6){
ans=add(sum,ans);
}
}
cout<<ans<<'\n';
return 0;
}