rt:
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cctype> // 包含 isdigit 函数的头文件
#include <random>
#include <vector>
#include <ctime>
#include <cmath>
namespace iofaster {
typedef long long lint ;
typedef long double dint ;
// 快读 1.0
lint read() {
char c ; lint x ;
bool b = true ;
for (c = getchar() ; !isdigit(c) ; c = getchar())
if (c == '-') b = false ;
for (x = 0 ; isdigit(c) ; c = getchar())
x = x * 10 + c - '0' ;
if (!b) x *= -1 ;
return x ;
}
// 快读 2.0
void input(lint &x) {
char c ;
bool b = true ;
for (c = getchar() ; !isdigit(c) ; c = getchar())
if (c == '-') b = false ;
for (x = 0 ; isdigit(c) ; c = getchar())
x = x * 10 + c - '0' ;
if (!b) x *= -1 ;
}
// 快写 1.0
void write(lint x) {
if (x < 0) putchar('-'), x *= -1 ;
if (x >= 10) write(x / 10) ;
putchar(x % 10 + '0') ;
}
// 快写 2.0
void output(lint x, char c) {
write(x) ;
putchar(c) ;
}
}
namespace FHQ_Treap {
typedef long long lint ;
typedef long double dint ;
struct Node {
lint Lazy ;
lint Size ;
lint val, rnd ;
lint Left, Right ;
} ;
lint root, idx ;
// 增大数组大小以避免越界风险
Node tree[lint(2e6 + 5)] ;
// 创建新的节点
lint get_Node(lint val) {
idx ++ ;
tree[idx].Size = 1 ;
tree[idx].val = val ;
tree[idx].rnd = rand() ;
return idx ;
}
// 向上更新父节点
void push_up(lint x) {
tree[x].Size = tree[tree[x].Left].Size + tree[tree[x].Right].Size + 1 ;
}
// 向下传播懒标记
void push_down(lint x) {
if (tree[x].Lazy) {
std::swap(tree[x].Left, tree[x].Right) ;
if (tree[x].Left) tree[tree[x].Left].Lazy ^= 1 ;
if (tree[x].Right) tree[tree[x].Right].Lazy ^= 1 ;
tree[x].Lazy = false ;
}
}
// 权值分裂: 当前在节点 now,将树分裂成以 x 为根(权值全部小于等于 k)、以 y 为根(权值全部大于 k)的两颗树
void split(lint now, lint k, lint &x, lint &y) {
if (!now) {
x = y = 0 ;
return ;
}
push_down(now) ;
if (tree[now].val <= k) {
x = now ;
split(tree[now].Right, k, tree[now].Right, y) ;
} else {
y = now ;
split(tree[now].Left, k, x, tree[now].Left) ;
}
push_up(now) ;
}
// 排名分裂: 当前在节点 now,将树分裂成以 x 为根(权值全部小于等于 k)、以 y 为根(权值全部大于 k)的两颗树
void division(lint now, lint k, lint &x, lint &y) {
if (!now) {
x = y = 0 ;
return ;
}
push_down(now) ;
if (k < tree[tree[now].Left].Size) {
y = now ;
lint son = tree[now].Left ;
division(son, k, x, son) ;
} else {
x = now ;
lint son = tree[now].Right ;
division(son, k - tree[tree[now].Left].Size - 1, son, y) ;
}
push_up(now) ;
}
// 合并: 合并以 x 为根和以 y 为根的两颗树(x 所有点的权值都小于 y 所有点的权值)
lint merge(lint x, lint y) {
if (!x || !y) return x | y ;
if (tree[x].rnd < tree[y].rnd) {
push_down(x) ;
tree[x].Right = merge(tree[x].Right, y) ;
push_up(x) ;
return x ;
} else {
push_down(y) ;
tree[y].Left = merge(x, tree[y].Left) ;
push_up(y) ;
return y ;
}
}
// 插入: 插入权值为 val 的点
void insert(lint val) {
lint x, y ;
split(root, val, x, y) ;
root = merge(merge(x, get_Node(val)), y) ;
}
// 区间删除: 删除给定权值为 val 的所有点
void remove(lint val) {
lint x, y, z ;
split(root, val, x, z) ;
split(x, val - 1, x, y) ;
root = merge(x, z) ;
}
// 单点删除: 删除给定权值为 val 的其中一个点
void Delete(lint val) {
lint x, y, z ;
split(root, val, x, z) ;
split(x, val - 1, x, y) ;
y = merge(tree[y].Left, tree[y].Right) ;
root = merge(merge(x, y), z) ;
}
// 区间翻转: 翻转排名从 l 到 r 的区间
void reverse(lint l, lint r) {
lint x, y, z ;
division(root, l - 1, x, y) ;
division(y, r - l + 1, y, z) ;
tree[y].Lazy ^= 1 ;
root = merge(merge(x, y), z) ;
}
// 求第 k 小的数
lint kth(lint now, lint k) {
while (now) {
if (k <= tree[tree[now].Left].Size) now = tree[now].Left ;
else if (k == tree[tree[now].Left].Size + 1) return tree[now].val ;
else {
k -= tree[tree[now].Left].Size + 1 ;
now = tree[now].Right ;
}
}
return -1 ;
}
// 查询权值为 val 的节点的排名
lint Rank(lint val) {
lint x, y ;
split(root, val - 1, x, y) ;
lint res = tree[x].Size + 1 ;
root = merge(x, y) ;
return res ;
}
// 查询权值为 val 的节点的前驱
lint Predecessor(lint val) {
lint x, y ;
split(root, val - 1, x, y) ;
lint res = kth(x, tree[x].Size) ;
root = merge(x, y) ;
return res ;
}
// 查询权值为 val 的节点的后继
lint Successor(lint val) {
lint x, y ;
split(root, val, x, y) ;
lint res = kth(y, 1) ;
root = merge(x, y) ;
return res ;
}
}
using namespace std ;
using namespace iofaster ;
using namespace FHQ_Treap ;
int main () {
srand(time(NULL)); // 初始化随机数种子
int n = read() ; // 数列的大小
int m = read() ; // 操作的数量
// 初始化数列
for (int i = 0; i < n; ++ i) {
int val = read() ;
insert(val) ;
}
// 执行操作
for (int i = 0 ; i < m ; ++ i) {
int op = read() ; // 操作类型
if (op == 1) { // 插入操作
int val = read() ;
insert(val) ;
} else if (op == 2) { // 删除操作
int val = read() ;
Delete(val) ;
} else if (op == 3) { // 区间反转操作
int l = read() ;
int r = read() ;
reverse(l, r) ;
}
}
return 0;
}