# 题目大意

$n$$n$个可重集，支持下列操作：

# 做法

1是加入，2是删除，3是合并。

mex用值域线段树做。

#include<cstdio>
#include<algorithm>
#include<set>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=500000+10,maxtot=15000000+10;
struct dong{
int x,y;
bool friend operator <(dong a,dong b){
return a.x<b.x||a.x==b.x&&a.y<b.y;
}
} zlt;
set<dong> his[maxn];
set<dong>::iterator it;
ll tree[maxtot],sum[maxtot];
int left[maxtot],right[maxtot],root[maxn];
bool bz[maxtot];
int i,j,k,l,t,n,m,tot,ans,mx,tim;
ll wdc;
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
int newnode(int x){
tot++;
tree[tot]=tree[x];
sum[tot]=sum[x];
left[tot]=left[x];
right[tot]=right[x];
bz[tot]=bz[x];
}
void insert(int &x,int l,int r,int a,int b){
x=newnode(x);
if (l==r){
if (!sum[x]&&b==-1) return;
sum[x]+=(ll)a*b;
if (sum[x]) bz[x]=1;else bz[x]=0;
if (bz[x]) tree[x]=a-1;else tree[x]=0;
return;
}
int mid=(l+r)/2;
if (a<=mid) insert(left[x],l,mid,a,b);else insert(right[x],mid+1,r,a,b);
sum[x]=sum[left[x]]+sum[right[x]];
bz[x]=bz[left[x]]&bz[right[x]];
tree[x]=max(tree[left[x]],tree[right[x]]-sum[left[x]]);
}
int merge(int x,int y,int l,int r){
if (!x||!y) return x+y;
if (l==r){
x=newnode(x);
sum[x]+=sum[y];
if (sum[x]) bz[x]=1;else bz[x]=0;
if (bz[x]) tree[x]=l-1;else tree[x]=0;
return x;
}
int mid=(l+r)/2;
x=newnode(x);
left[x]=merge(left[x],left[y],l,mid);
right[x]=merge(right[x],right[y],mid+1,r);
sum[x]=sum[left[x]]+sum[right[x]];
bz[x]=bz[left[x]]&bz[right[x]];
tree[x]=max(tree[left[x]],tree[right[x]]-sum[left[x]]);
return x;
}
void query(int x,int l,int r){
if (bz[x]){
ans=r+1;
return;
}
if (l==r){
ans=l;
return;
}
int mid=(l+r)/2;
if (bz[left[x]]) query(right[x],mid+1,r);else query(left[x],l,mid);
}
if (tree[x]<=wdc){
wdc+=sum[x];
wdc++;
return;
}
if (l==r){
wdc++;
return;
}
int mid=(l+r)/2;
if (tree[left[x]]<=wdc){
wdc+=sum[left[x]];
}
}
void travel(int x,int l,int r){
if (!x) return;
if (l==r){
while (sum[x]){
printf("%d ",l);
sum[x]-=(ll)l;
}
return;
}
int mid=(l+r)/2;
travel(left[x],l,mid);
travel(right[x],mid+1,r);
}
int main(){
freopen("forgive.in","r",stdin);freopen("forgive.out","w",stdout);
mx=500000;
fo(i,1,n){
zlt.x=0;
zlt.y=0;
his[i].insert(zlt);
}
while (m--){
tim++;
j=(j+ans-1)%n+1;
if (t==1){
insert(root[j],1,mx,k,1);
zlt.x=tim;
zlt.y=root[j];
his[j].insert(zlt);
}
else if (t==2){
insert(root[j],1,mx,k,-1);
zlt.x=tim;
zlt.y=root[j];
his[j].insert(zlt);
}
else if (t==3){
k=(k+ans-1)%n+1;
if (j!=k){
root[j]=merge(root[j],root[k],1,mx);
root[k]=0;
zlt.x=tim;
zlt.y=root[j];
his[j].insert(zlt);
zlt.y=root[k];
his[k].insert(zlt);
}
}
else if (t==4){
query(root[j],1,mx);
wdc=0;
printf("%d %lld\n",ans,wdc);
}
else if (t==5){
k--;
zlt.x=k;
zlt.y=tot+1;
his[j].insert(zlt);
it=his[j].lower_bound(zlt);
it--;
k=(*it).y;
query(k,1,mx);
wdc=0;
}