题意
维护一个集合,初始为 \([0,a]\cap \mathbf{N}\),要求支持以下操作:
- 插入 \(x\),保证 \(x\) 未被加入过;
- 删除 \(x\);
- 把最近一次删除时间最早的、不在集合中的数插入回矩阵。
求每一次操作后集合的 \(\operatorname{mex}\)。
多组数据,数据由随机数生成器生成,其中有参数可以控制操作 3 的频率。
\(m\leq 10^6\),\(T\leq 50\)。
题解
标算是 \(O(mT)\) 的,这里有一种 \(O(\text{玄学})\) 的做法:
- 由于数据随机,维护 \(ans\),直接在操作 1、3 时暴力移 \(ans\),操作 2 时 \(ans\gets \min(ans,x)\);
- 对于 \(c=2\) 而 \(a\) 较大的情况,操作 \(3\) 占了几乎一半,于是集合整体不会被分成很多段,用
set
维护桶的差分。
代码:
#include<bits/stdc++.h>
using namespace std;
long long getint(){
long long ans=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
ans=ans*10+c-'0';
c=getchar();
}
return ans*f;
}
const int M=2e6+10,mod=998244353;
int m,a,b,c,d;
unsigned int seed;
inline unsigned int randnum(){
seed^=(seed<<13);
seed^=(seed>>17);
seed^=(seed<<5);
return seed;
}
inline int getp(){
if(randnum()%c==0)return -1;
else return randnum()%b;
}
bool f[M<<1],g[M<<1];
int ans=0;
struct que{
int a[M];
int *l,*r;
que(){ l=r=a; }
inline void push(int x){ *(r++)=x; }
inline void pop(){ l++; }
inline int size(){ return r-l; }
inline void init(){ l=r=a; }
inline int front(){ return *l; }
};
que q;
set<int>s;
void modi(int x){
if(s.count(x))s.erase(x);
else s.insert(x);
}
inline void op1(int p){
f[p]=g[p]=1;
if(c>2){
while(f[ans])++ans;
}else{
modi(p);modi(p+1);
set<int>::iterator b=s.begin();
if(*b==0)ans=*(++b);
else ans=0;
}
}
inline void op2(int p){
f[p]=0;
if(c>2){}else{
modi(p);modi(p+1);
if(s.size()){
set<int>::iterator b=s.begin();
if(*b==0)ans=*(++b);
else ans=0;
}else ans=0;
}
q.push(p);
ans=min(ans,p);
}
inline void op3(){
op1(q.front());
q.pop();
}
int main(){
int T=getint();
while(T --> 0){
m=getint(),seed=getint(),a=getint(),b=getint(),c=getint(),d=getint();
for(int i=0;i<=a;i++)f[i]=g[i]=1;ans=a+1;
if(c<=2)s.insert(0),s.insert(a+1);
long long res=0;
for(int i=1;i<=m;i++){
int p=getp();
if(p==-1){
if(!q.size())continue;
if(d)continue; else op3();
}else{
if(!g[p]){ op1(p); }
else if(f[p]){ if(d)continue;else op2(p); }
else if(q.size()){ if(d)continue;else op3(); }
else continue;
}
res^=ans*(i*1ll*i%mod+7ll*i%mod)%mod;
}
printf("%lld\n",res);
q.init();
memset(f,0,sizeof(bool)*(b+2));
memset(g,0,sizeof(bool)*(b+2));
s.clear();
}
}