取$M=\sqrt{300000}$。
設$g[i]$表示程式設計師的$\bmod i$最小的值。
若$Y<M$,那麼可以在$O(M)$時間內完成對所有$g[i]$的修改,$O(1)$時間內完成查詢。
若$Y\geq M$,那麼列舉$Y$的倍數,等價於查詢一段區間內的最小值,可以通過分塊做到$O(M)$修改,$O(1)$查詢。
因為倍數不超過$M$個,所以詢問的總複雜度為$O(M)$。
所以總時間複雜度為$O(n\sqrt{300000})$。
#include<cstdio> const int N=300010,M=550; int n=300000,m=n/M,q,i,x,pos[N],st[M],f[N],tag[M],g[M];char op[5]; inline void up(int&a,int b){if(a>b)a=b;} inline void add(int x){ for(int i=1;i<M;i++)up(g[i],x%i); for(int i=st[pos[x]];i<=x;i++)up(f[i],x); for(int i=pos[x]-1;~i;i--)up(tag[i],x); } inline int ask(int x){ if(!x)x++; int t=f[x]; up(t,tag[pos[x]]); return t; } inline int query(int x){ if(x<M)return g[x]; int t=N; for(int i=0,j=x;i<=n;i=j,j+=x){ if(j>n)j=n+1; int y=ask(i); if(y<j)up(t,y-i); } return t; } int main(){ for(i=1;i<=n;i++)pos[i]=i/M; for(i=n;i;i--)st[pos[i]]=i; for(i=1;i<=n;i++)f[i]=N; for(i=0;i<=m;i++)tag[i]=N; for(i=1;i<M;i++)g[i]=N; scanf("%d",&q); while(q--){ scanf("%s%d",op,&x); if(op[0]=='A')add(x);else printf("%d\n",query(x)); } return 0; }