#line 1 "verify/binary-search-tree/UNIT_rbst_array.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/aplusb"
#line 2 "template/template.hpp"
#include <bits/stdc++.h>
using namespace std;
#line 2 "template/macro.hpp"
#define rep(i, a, b) for (int i = (a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b) - 1; i >= (a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())
#define YN(b) cout << ((b) ? "YES" : "NO") << "\n";
#define Yn(b) cout << ((b) ? "Yes" : "No") << "\n";
#define yn(b) cout << ((b) ? "yes" : "no") << "\n";
#line 6 "template/template.hpp"
#line 2 "template/util.hpp"
using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
template <class T, class S = T>
S SUM(const vector<T>& a) {
return accumulate(ALL(a), S(0));
}
template <class T>
inline bool chmin(T& a, T b) {
if (a > b) {
a = b;
return true;
}
return false;
}
template <class T>
inline bool chmax(T& a, T b) {
if (a < b) {
a = b;
return true;
}
return false;
}
template <class T>
int popcnt(T x) {
return __builtin_popcountll(x);
}
template <class T>
int topbit(T x) {
return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <class T>
int lowbit(T x) {
return (x == 0 ? -1 : __builtin_ctzll(x));
}
#line 8 "template/template.hpp"
#line 2 "template/inout.hpp"
struct Fast {
Fast() {
cin.tie(nullptr);
ios_base::sync_with_stdio(false);
cout << fixed << setprecision(15);
}
} fast;
template <class T1, class T2>
istream& operator>>(istream& is, pair<T1, T2>& p) {
return is >> p.first >> p.second;
}
template <class T1, class T2>
ostream& operator<<(ostream& os, const pair<T1, T2>& p) {
return os << p.first << " " << p.second;
}
template <class T>
istream& operator>>(istream& is, vector<T>& a) {
for (auto& v : a) is >> v;
return is;
}
template <class T>
ostream& operator<<(ostream& os, const vector<T>& a) {
for (auto it = a.begin(); it != a.end();) {
os << *it;
if (++it != a.end()) os << " ";
}
return os;
}
template <class T>
ostream& operator<<(ostream& os, const set<T>& st) {
os << "{";
for (auto it = st.begin(); it != st.end();) {
os << *it;
if (++it != st.end()) os << ",";
}
os << "}";
return os;
}
template <class T1, class T2>
ostream& operator<<(ostream& os, const map<T1, T2>& mp) {
os << "{";
for (auto it = mp.begin(); it != mp.end();) {
os << it->first << ":" << it->second;
if (++it != mp.end()) os << ",";
}
os << "}";
return os;
}
void in() {}
template <typename T, class... U>
void in(T& t, U&... u) {
cin >> t;
in(u...);
}
void out() { cout << "\n"; }
template <typename T, class... U, char sep = ' '>
void out(const T& t, const U&... u) {
cout << t;
if (sizeof...(u)) cout << sep;
out(u...);
}
#line 10 "template/template.hpp"
#line 2 "template/debug.hpp"
#ifdef LOCAL
#define debug 1
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define debug 0
#define show(...) true
#endif
template <class T>
void _show(int i, T name) {
cerr << '\n';
}
template <class T1, class T2, class... T3>
void _show(int i, const T1& a, const T2& b, const T3&... c) {
for (; a[i] != ',' && a[i] != '\0'; i++) cerr << a[i];
cerr << ":" << b << " ";
_show(i + 1, a, c...);
}
#line 2 "binary-search-tree/rbst-base.hpp"
template <class Node>
struct RBSTBase {
using Ptr = Node*;
template <typename... Args>
inline Ptr my_new(Args... args) {
return new Node(args...);
}
inline void my_del(Ptr t) { delete t; }
inline Ptr make_tree() const { return nullptr; }
int size(Ptr t) const { return count(t); }
Ptr merge(Ptr l, Ptr r) {
if (!l || !r) return l ? l : r;
if (int((rng() * (l->cnt + r->cnt)) >> 32) < l->cnt) {
push(l);
l->r = merge(l->r, r);
return update(l);
} else {
push(r);
r->l = merge(l, r->l);
return update(r);
}
}
pair<Ptr, Ptr> split(Ptr t, int k) {
if (!t) return {nullptr, nullptr};
push(t);
if (k <= count(t->l)) {
auto s = split(t->l, k);
t->l = s.second;
return {s.first, update(t)};
} else {
auto s = split(t->r, k - count(t->l) - 1);
t->r = s.first;
return {update(t), s.second};
}
}
Ptr build(int l, int r, const vector<decltype(Node::key)>& v) {
if (l + 1 == r) return my_new(v[l]);
int m = (l + r) >> 1;
Ptr pm = my_new(v[m]);
if (l < m) pm->l = build(l, m, v);
if (m + 1 < r) pm->r = build(m + 1, r, v);
return update(pm);
}
Ptr build(const vector<decltype(Node::key)>& v) {
return build(0, (int)v.size(), v);
}
template <typename... Args>
void insert(Ptr& t, int k, const Args&... args) {
auto x = split(t, k);
t = merge(merge(x.first, my_new(args...)), x.second);
}
void erase(Ptr& t, int k) {
auto x = split(t, k);
auto y = split(x.second, 1);
my_del(y.first);
t = merge(x.first, y.second);
}
protected:
static uint64_t rng() {
static uint64_t x_ = 123456789ull;
return x_ ^= x_ << 7, x_ ^= x_ >> 9, x_ & 0xFFFFFFFFull;
}
inline int count(const Ptr t) const { return t ? t->cnt : 0; }
virtual void push(Ptr) = 0;
virtual Ptr update(Ptr) = 0;
};
/**
* @brief Randomized Binary Search Tree (基底クラス)
* @docs docs/binary-search-tree/rbst-base.md
*/
#line 3 "binary-search-tree/rbst-array.hpp"
template <typename T>
struct RBSTArrayNode {
typename RBSTBase<RBSTArrayNode>::Ptr l, r;
T key;
int cnt;
RBSTArrayNode(const T& t = T()) : l(), r(), key(t), cnt(1) {}
};
template <class T>
struct RBSTArray : RBSTBase<RBSTArrayNode<T>> {
using Node = RBSTArrayNode<T>;
using base = RBSTBase<Node>;
using base::merge;
using base::split;
using typename base::Ptr;
RBSTArray() = default;
T get(Ptr& t, int k) {
auto x = split(t, k);
auto y = split(x.second, 1);
T v = y.first->key;
t = merge(x.first, merge(y.first, y.second));
return v;
}
void set(Ptr& t, int k, T v) {
auto x = split(t, k);
auto y = split(x.second, 1);
y.first->key = v;
t = merge(x.first, merge(y.first, y.second));
}
protected:
Ptr update(Ptr t) override {
t->cnt = 1;
if (t->l) t->cnt += t->l->cnt;
if (t->r) t->cnt += t->r->cnt;
return t;
}
void push(Ptr t) override {}
};
/**
* @brief 挿入/削除の可能な配列 (乱択二分探索木)
*/
#line 2 "util/xorshift.hpp"
namespace XORShift {
unsigned int xor32() {
static unsigned int x = 123456789u;
x ^= x << 13, x ^= x >> 17, x ^= x << 5;
return x;
}
unsigned long long xor64() {
static unsigned long long x = 123456789ull;
x ^= x << 13, x ^= x >> 7, x ^= x << 17;
return x;
}
}; // namespace XORShift
/**
* @brief XOR shift
*/
#line 6 "verify/binary-search-tree/UNIT_rbst_array.test.cpp"
void test() {
vector<int> a;
RBSTArray<int> ar;
auto t = ar.make_tree();
rep(loop, 0, 10000) {
int type = XORShift::xor32() % 3;
if (a.empty()) type = 0;
if (type == 0) {
int x = XORShift::xor32() % (a.size() + 1);
int v = XORShift::xor32();
a.insert(a.begin() + x, v);
ar.insert(t, x, v);
} else if (type == 1) {
int x = XORShift::xor32() % a.size();
int v = XORShift::xor32();
a[x] = v;
ar.set(t, x, v);
} else {
int x = XORShift::xor32() % a.size();
a.erase(a.begin() + x);
ar.erase(t, x);
}
assert(a.size() == ar.size(t));
rep(i, 0, a.size()) assert(a[i] == ar.get(t, i));
}
}
int main() {
test();
int a, b;
in(a, b);
out(a + b);
}