Description

需要支持两种操作
1:在人物集合 S 中加入一个新的程序员,其代号为 X,保证 X 在当前集合中不存在。
2:在当前的人物集合中询问程序员的mod Y 最小的值。 (为什么统计这个?因为拯救
过世界的人太多了,只能取模)
保证第一次为操作1
N≤100000, 1≤X,Y≤300000

Solution

直接统计,很难办
可以用平衡规划的思想搞一波
【杂题】[BZOJ4320]【ShangHai2006】Homework【平衡规划】【并查集】_#include
对于所有【杂题】[BZOJ4320]【ShangHai2006】Homework【平衡规划】【并查集】_杂题_02的询问,我们在修改时暴力将这些询问更新即可,然后直接查询。

对于所有【杂题】[BZOJ4320]【ShangHai2006】Homework【平衡规划】【并查集】_#include_03的询问,我们可以离线,将询问和修改倒过来,用并查集维护右边的第一个是谁,对于每个询问直接枚举倍数即可(当然也可以值域分块,相当于区间查询最小值)。
复杂度【杂题】[BZOJ4320]【ShangHai2006】Homework【平衡规划】【并查集】_并查集_04

Code

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define N 300005
using namespace std;
int mx,n,ri[N],ask[N][2],ans[N],qs[550];
int fd(int k)
{
if(ri[k]==k) return k;
if(!ri[k]) return 0;
return ri[k]=fd(ri[k]);
}
int main()
{
cin>>n;
mx=0;
memset(qs,107,sizeof(qs));
fo(i,1,n)
{
char ch;
int x;
scanf("\n%c %d",&ch,&x);
ask[i][0]=ch-'A';
ask[i][1]=x;
if(ch=='A') mx=max(mx,x),ri[x]=x;
}
int n1=sqrt(mx);
memset(ans,107,sizeof(ans));
fo(i,1,n)
{
if(ask[i][0]==0) fo(j,1,n1) qs[j]=min(qs[j],ask[i][1]%j);
else if(ask[i][1]<=n1) ans[i]=qs[ask[i][1]];
}
fod(i,mx,0) if(!ri[i]) ri[i]=ri[i+1];
fod(i,n,1)
{
if(!ask[i][0]) ri[ask[i][1]]=fd(ask[i][1]+1);
else if(ask[i][1]>n1)
{
for(int j=0;ask[i][1]*j<=mx;j++)
{
int p=fd(ask[i][1]*j);
if(p) ans[i]=min(ans[i],p%ask[i][1]);
}
}
}
fo(i,1,n) if(ask[i][0]==1) printf("%d\n",ans[i]);
}