//非旋转的Treap树
#include<bits/stdc++.h>
using namespace std;
const int INF=0x7fffffff;
struct Node *nil; // 自定义的空指针,防止翻车(RE)
struct Node {
Node *ch[2]; // 结点的左右孩子。为什么不分开写成lc,rc呢?往后就知道了
int v, s, c; // v表示该结点的值,s表示以该结点为根的子树大小,c表示权值v的结点数量(合并了相同权值的结点),即v的副本数量
int r; // Treap专有的随机数,是大根堆的关键字
void maintain() { // 维护当前结点的信息
s = ch[0]->s + ch[1]->s + c;
}
Node(int v) : v(v), c(1), s(1), r(rand()) { ch[0] = ch[1] = nil; } // 新建结点
} *root;
void init() {
srand(0); // 随机数初始化
nil = new Node(0); // 空指针初始化
root = nil->ch[0] = nil->ch[1] = nil; // 左右孩子指向自身
nil->s = nil->c = 0; // 防止空指针影响后面的操作
}
void split(Node *o, int v, Node* &l, Node* &r) {
if (o == nil) { l = r = nil; return; } // 到了空结点两边附上空后结束
if (o->v < v) { l = o; split(o->ch[1], v, l->ch[1], r); l->maintain(); } // 第一种情况。注意分裂后要及时维护信息
else { r = o; split(o->ch[0], v, l, r->ch[0]); r->maintain(); } // 第二种情况。同上
}
Node* merge(Node *a, Node *b) {
if (a == nil) return b; // 如果a空返回b
if (b == nil) return a; // 如果b空返回a
if (a->r > b->r) { a->ch[1] = merge(a->ch[1], b); a->maintain(); return a; } // 比较两者的随机关键字,大的先合并
else { b->ch[0] = merge(a, b->ch[0]); b->maintain(); return b; }
}
void insert(Node* &rt, int v) {
Node *l, *r;
split(rt, v, l, r);
rt = merge(merge(l, new Node(v)), r);
}
void remove(Node* &rt, int v) {
Node *l, *mid, *r;
split(rt, v, l, r);
split(r, v+1, mid, r);
rt = merge(merge(l, merge(mid->ch[0], mid->ch[1])), r);
delete mid;
}
//v的排名
int get_rank(Node* o, int v) {
/*
10
/\
4
\
10
/\
7
/\
.. 10
有错
if (v < o->v) return get_rank(o->ch[0], v); // v在左子树中
if (o->ch[0]&&o->ch[0]->v==v) return get_rank(o->ch[0],v);
if (o->v== v) return o->ch[0]->s + 1; // 找到v
return get_rank(o->ch[1], v) + o->ch[0]->s + o->c;
// v在右子树中,此时要将左子树中的所有元素以及根的元素数统计起来
*/
/*
int ans=0;
while(o!=nil)
{
if (o->v>=v)
{
o=o->ch[0];
}
else
{
ans+=o->ch[0]->s+1;
o=o->ch[1];
}
}
return ans+1;
*/
if (o==nil) return 1;
if (o->v>=v) return get_rank(o->ch[0],v);
else return o->ch[0]->s+1+get_rank(o->ch[1],v);
}
//第k小数
int get_val(Node* o, int k) {
if (k <= o->ch[0]->s) return get_val(o->ch[0], k); // 排名为k的数在左子树中
else if (k == o->ch[0]->s + o->c) return o->v; // 为o
else return get_val(o->ch[1], k - o->ch[0]->s - o->c); // 在右子树中
}
int get_pre(Node *o, int v) { // 查前驱
if (o == nil) return -INF; // 找到空结点返回无穷小目的是不干扰其它解
if (o->v >= v) return get_pre(o->ch[0], v); // v大于当前结点o的值,向左走找小一点的值
return max(o->v, get_pre(o->ch[1], v)); // 否则向右走找更大的值并与当前值比较
/*
有点慢
if (o == nil) return -INF; // 找到空结点返回无穷小目的是不干扰其它解
return get_val(o,get_rank(o,v)-1);
*/
}
int get_next(Node *o, int v) { // 查后继,与上面完全相反
/*
if (o == nil) return INF;
if (o->v <= v) return get_next(o->ch[1], v);
return min(o->v, get_next(o->ch[0], v));
*/
return get_val(o,get_rank(o,v+1));//有点慢
}
int main()
{
int n,m,op,x,last=0,ans=0;
init();
scanf("%d %d",&n,&m);
while(n--)
{
scanf("%d",&x);
insert(root,x);
}
while(m--)
{
scanf("%d %d",&op,&x);
x=last^x;
if (op==1)
insert(root,x);
else if(op==2)
remove(root,x);
else if(op==3)
{
last=get_rank(root,x);
ans^=last;
}
else if(op==4)
{
last=get_val(root,x);
ans^=last;
}
else if(op==5)
{
last=get_pre(root,x);
ans^=last;
}
else if(op==6)
{
last=get_next(root,x);
ans^=last;
}
}
cout<<ans<<endl;
}