#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Node {
ll start; // first value of the segment
ll len; // number of elements in the segment
ll seg_sum; // sum of this segment: len*(2*start + len - 1)/2
ll size; // total number of elements in the subtree
ll total_sum; // sum of all elements in the subtree
Node *left, *right, *parent;
Node(ll s, ll l) : start(s), len(l), left(nullptr), right(nullptr), parent(nullptr) {
seg_sum = l * (2*s + l - 1) / 2;
size = l;
total_sum = seg_sum;
}
};
Node* root = nullptr;
set<pair<ll, Node*>> segMap; // maps start value to the node containing that segment
ll next_A = 1; // next number to take from sequence A
// ---------- Splay tree utilities ----------
void update(Node* x) {
if (!x) return;
x->size = x->len;
x->total_sum = x->seg_sum;
if (x->left) {
x->size += x->left->size;
x->total_sum += x->left->total_sum;
}
if (x->right) {
x->size += x->right->size;
x->total_sum += x->right->total_sum;
}
}
void rotate(Node* x) {
Node* p = x->parent;
Node* g = p->parent;
if (p->left == x) {
p->left = x->right;
if (x->right) x->right->parent = p;
x->right = p;
p->parent = x;
} else {
p->right = x->left;
if (x->left) x->left->parent = p;
x->left = p;
p->parent = x;
}
update(p);
update(x);
x->parent = g;
if (g) {
if (g->left == p) g->left = x;
else g->right = x;
}
}
// Splay x to the root of its tree, and update the tree root pointer.
void splay(Node*& treeRoot, Node* x) {
if (!x) return;
while (x->parent) {
Node* p = x->parent;
Node* g = p->parent;
if (!g) {
rotate(x);
} else if ((g->left == p) == (p->left == x)) {
rotate(p);
rotate(x);
} else {
rotate(x);
rotate(x);
}
}
treeRoot = x;
}
Node* find_max(Node* node) {
while (node->right) node = node->right;
return node;
}
// Merge two trees: all elements in left are before those in right.
Node* merge(Node*& left, Node*& right) {
if (!left) {
left = right;
return left;
}
if (!right) return left;
Node* max_left = find_max(left);
splay(left, max_left); // now left is max_left, with no right child
left->right = right;
right->parent = left;
update(left);
return left;
}
// ---------- Segment map management ----------
void insert_into_segMap(Node* node) {
segMap.insert({node->start, node});
}
void remove_from_segMap(Node* node) {
auto it = segMap.find({node->start, node});
if (it != segMap.end()) segMap.erase(it);
}
// Find the segment that contains value v.
Node* find_segment(ll v) {
auto it = segMap.upper_bound({v, nullptr});
if (it == segMap.begin()) return nullptr;
--it;
Node* node = it->second;
if (node->start <= v && v <= node->start + node->len - 1)
return node;
// Should not happen if the map is consistent
return nullptr;
}
// ---------- Core operations ----------
// Split the tree rooted at 'treeRoot' into two trees:
// left tree contains the first k elements, right tree the rest.
pair<Node*, Node*> split_by_index(Node*& treeRoot, ll k) {
if (!treeRoot) return {nullptr, nullptr};
if (k == 0) {
Node* right = treeRoot;
right->parent = nullptr;
treeRoot = nullptr;
return {nullptr, right};
}
if (k == treeRoot->size) {
Node* left = treeRoot;
left->parent = nullptr;
treeRoot = nullptr;
return {left, nullptr};
}
Node* cur = treeRoot;
ll kk = k; // remaining elements to skip
while (true) {
ll left_size = (cur->left ? cur->left->size : 0);
if (kk <= left_size) {
cur = cur->left;
} else if (kk <= left_size + cur->len) {
break;
} else {
kk -= left_size + cur->len;
cur = cur->right;
}
}
// cur contains the k-th element
splay(treeRoot, cur);
// now treeRoot == cur
ll left_size = (treeRoot->left ? treeRoot->left->size : 0);
ll offset = kk - left_size; // 1-based offset inside the node
if (offset == treeRoot->len) {
// whole node goes to the left tree
Node* left = treeRoot->left;
Node* right = treeRoot->right;
treeRoot->left = treeRoot->right = nullptr;
update(treeRoot);
if (left) left->parent = nullptr;
if (right) right->parent = nullptr;
Node* L_tree = merge(left, treeRoot);
treeRoot = nullptr;
return {L_tree, right};
} else {
// split the node
Node* left_node = new Node(treeRoot->start, offset);
Node* right_node = new Node(treeRoot->start + offset, treeRoot->len - offset);
remove_from_segMap(treeRoot);
insert_into_segMap(left_node);
insert_into_segMap(right_node);
Node* left_child = treeRoot->left;
Node* right_child = treeRoot->right;
delete treeRoot;
Node* L_tree = merge(left_child, left_node);
Node* R_tree = merge(right_node, right_child);
if (L_tree) L_tree->parent = nullptr;
if (R_tree) R_tree->parent = nullptr;
treeRoot = nullptr;
return {L_tree, R_tree};
}
}
// Delete an entire subtree and remove all its segments from the map.
void delete_tree(Node* node) {
if (!node) return;
delete_tree(node->left);
delete_tree(node->right);
remove_from_segMap(node);
delete node;
}
// Type 1: insert K numbers after value X
void type1(ll X, ll K) {
Node* u = find_segment(X);
// Guaranteed that u exists
splay(root, u);
Node* L = root->left;
Node* R = root->right;
if (L) L->parent = nullptr;
if (R) R->parent = nullptr;
root->left = root->right = nullptr;
ll d = X - root->start;
Node* left_node = nullptr;
Node* right_node = nullptr;
if (d + 1 < root->len) {
left_node = new Node(root->start, d + 1);
right_node = new Node(X + 1, root->len - (d + 1));
} else {
left_node = new Node(root->start, root->len);
right_node = nullptr;
}
remove_from_segMap(root);
insert_into_segMap(left_node);
if (right_node) insert_into_segMap(right_node);
delete root;
Node* new_node = new Node(next_A, K);
next_A += K;
insert_into_segMap(new_node);
Node* A = merge(L, left_node);
Node* B = merge(A, new_node);
if (right_node) {
Node* C = merge(B, right_node);
root = merge(C, R);
} else {
root = merge(B, R);
}
}
// Type 2: delete H numbers immediately after value Y
void type2(ll Y, ll H) {
Node* u = find_segment(Y);
splay(root, u);
Node* L = root->left;
Node* R = root->right;
if (L) L->parent = nullptr;
if (R) R->parent = nullptr;
root->left = root->right = nullptr;
ll d = Y - root->start;
Node* left_node = nullptr;
Node* right_node = nullptr;
if (d + 1 < root->len) {
left_node = new Node(root->start, d + 1);
right_node = new Node(Y + 1, root->len - (d + 1));
} else {
left_node = new Node(root->start, root->len);
right_node = nullptr;
}
remove_from_segMap(root);
insert_into_segMap(left_node);
if (right_node) insert_into_segMap(right_node);
delete root;
Node* A = merge(L, left_node);
Node* C = nullptr;
if (right_node) {
C = merge(right_node, R);
} else {
C = R;
}
if (!C) {
root = A;
return;
}
Node* C_root = C;
pair<Node*, Node*> split_result = split_by_index(C_root, H);
Node* P1 = split_result.first;
Node* P2 = split_result.second;
delete_tree(P1);
root = merge(A, P2);
}
// Type 3: return sum of elements from index L to R (1-based)
ll type3(ll L, ll R) {
pair<Node*, Node*> split1 = split_by_index(root, L - 1);
Node* left = split1.first;
Node* mid_right = split1.second;
pair<Node*, Node*> split2 = split_by_index(mid_right, R - L + 1);
Node* mid = split2.first;
Node* right = split2.second;
ll ans = mid->total_sum;
Node* temp = merge(left, mid);
root = merge(temp, right);
return ans;
}
int main() {
// Initial sequence: only one element 0
root = new Node(0, 1);
insert_into_segMap(root);
int Q;
scanf("%d", &Q);
while (Q--) {
int op;
scanf("%d", &op);
if (op == 1) {
ll X, K;
scanf("%lld %lld", &X, &K);
type1(X, K);
} else if (op == 2) {
ll Y, H;
scanf("%lld %lld", &Y, &H);
type2(Y, H);
} else {
ll L, R;
scanf("%lld %lld", &L, &R);
printf("%lld\n", type3(L, R));
}
}
// Cleanup (not strictly necessary)
delete_tree(root);
return 0;
}