This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://judge.yosupo.jp/problem/aplusb"
#include "my_template.hpp"
#include "ds/unionfind/unionfind.hpp"
#include "random/shuffle.hpp"
#include "other/timer.hpp"
#include "ds/fastset.hpp"
#include "ds/decremental_fastset.hpp"
// ackerman. memory 多め
struct Decremental_FastSet_UF_ONLY {
int n;
UnionFind uf;
vc<int> L, R;
Decremental_FastSet_UF_ONLY(int n) : n(n), uf(n + 2), L(n + 2), R(n + 2) {
FOR(i, n + 2) L[i] = i, R[i] = i;
}
void erase(int i) {
assert(0 <= i && i < n);
++i;
int l = L[uf[i - 1]], r = R[uf[i]];
uf.merge(i, i - 1);
L[uf[i]] = l, R[uf[i]] = r;
}
int prev(int i) {
assert(-1 <= i);
chmin(i, n - 1);
return L[uf[i + 1]] - 1;
}
int next(int i) {
assert(i <= n);
chmax(i, 0);
return R[uf[i]];
}
};
vc<pair<int, int>> sol1(vc<int> A, vc<int> B) {
int N = len(A);
FastSet FS(N, [&](int i) -> int { return 1; });
vc<pair<int, int>> ANS(N);
FOR(i, N) {
FS.erase(A[i]);
ANS[i] = {FS.prev(B[i]), FS.next(B[i])};
}
return ANS;
}
vc<pair<int, int>> sol2(vc<int> A, vc<int> B) {
int N = len(A);
Decremental_FastSet FS(N);
vc<pair<int, int>> ANS(N);
FOR(i, N) {
FS.erase(A[i]);
ANS[i] = {FS.prev(B[i]), FS.next(B[i])};
}
return ANS;
}
vc<pair<int, int>> sol3(vc<int> A, vc<int> B) {
int N = len(A);
Decremental_FastSet_UF_ONLY FS(N);
vc<pair<int, int>> ANS(N);
FOR(i, N) {
FS.erase(A[i]);
ANS[i] = {FS.prev(B[i]), FS.next(B[i])};
}
return ANS;
}
void test() {
vc<double> X, Y, Z;
FOR(100) {
int N = 1 << 20;
vc<int> A(N);
FOR(i, N) A[i] = i;
shuffle(A);
vc<int> B(N);
FOR(i, N) B[i] = RNG(0, N);
vc<pair<int, int>> ANS1, ANS2, ANS3;
{
Timer timer;
timer.start();
ANS1 = sol1(A, B);
X.eb(timer());
}
{
Timer timer;
timer.start();
ANS2 = sol2(A, B);
Y.eb(timer());
}
{
Timer timer;
timer.start();
ANS3 = sol3(A, B);
Z.eb(timer());
}
// print(X.back(), Y.back(), Z.back());
assert(ANS1 == ANS2);
assert(ANS1 == ANS3);
}
// print(SUM<double>(X));
// print(SUM<double>(Y));
// print(SUM<double>(Z));
}
void solve() {
int a, b;
cin >> a >> b;
cout << a + b << "\n";
}
signed main() {
test();
solve();
}
#line 1 "test/1_mytest/decremental_fastset.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/aplusb"
#line 1 "my_template.hpp"
#if defined(LOCAL)
#include <my_template_compiled.hpp>
#else
#if defined(__GNUC__)
#include <bits/allocator.h>
#pragma GCC optimize("Ofast,unroll-loops")
#pragma GCC target("avx2,popcnt")
#endif
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
using i128 = __int128;
using u128 = unsigned __int128;
using f128 = __float128;
template <class T>
constexpr T infty = 0;
template <>
constexpr int infty<int> = 1'010'000'000;
template <>
constexpr ll infty<ll> = 2'020'000'000'000'000'000;
template <>
constexpr u32 infty<u32> = infty<int>;
template <>
constexpr u64 infty<u64> = infty<ll>;
template <>
constexpr i128 infty<i128> = i128(infty<ll>) * 2'000'000'000'000'000'000;
template <>
constexpr double infty<double> = numeric_limits<double>::infinity();
template <>
constexpr long double infty<long double> =
numeric_limits<long double>::infinity();
using pi = pair<ll, ll>;
using vi = vector<ll>;
template <class T>
using vc = vector<T>;
template <class T>
using vvc = vector<vc<T>>;
template <class T>
using vvvc = vector<vvc<T>>;
template <class T>
using vvvvc = vector<vvvc<T>>;
template <class T>
using pq_max = priority_queue<T>;
template <class T>
using pq_min = priority_queue<T, vector<T>, greater<T>>;
#define vv(type, name, h, ...) \
vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define vvv(type, name, h, w, ...) \
vector<vector<vector<type>>> name( \
h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...) \
vector<vector<vector<vector<type>>>> name( \
a, vector<vector<vector<type>>>( \
b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
// https://trap.jp/post/1224/
#define FOR1(a) for (ll _ = 0; _ < ll(a); ++_)
#define FOR2(i, a) for (ll i = 0; i < ll(a); ++i)
#define FOR3(i, a, b) for (ll i = a; i < ll(b); ++i)
#define FOR4(i, a, b, c) for (ll i = a; i < ll(b); i += (c))
#define FOR1_R(a) for (ll i = (a) - 1; i >= ll(0); --i)
#define FOR2_R(i, a) for (ll i = (a) - 1; i >= ll(0); --i)
#define FOR3_R(i, a, b) for (ll i = (b) - 1; i >= ll(a); --i)
#define overload4(a, b, c, d, e, ...) e
#define overload3(a, b, c, d, ...) d
#define FOR(...) overload4(__VA_ARGS__, FOR4, FOR3, FOR2, FOR1)(__VA_ARGS__)
#define FOR_R(...) overload3(__VA_ARGS__, FOR3_R, FOR2_R, FOR1_R)(__VA_ARGS__)
#define all(x) (x).begin(), (x).end()
#define len(x) ll(x.size())
#define elif else if
#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second
#define stoi stoll
int popcnt(int x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(ll x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }
int popcnt_sgn(int x) { return (__builtin_parity(unsigned(x)) & 1 ? -1 : 1); }
int popcnt_sgn(u32 x) { return (__builtin_parity(x) & 1 ? -1 : 1); }
int popcnt_sgn(ll x) { return (__builtin_parityll(x) & 1 ? -1 : 1); }
int popcnt_sgn(u64 x) { return (__builtin_parityll(x) & 1 ? -1 : 1); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 1, 2)
int topbit(int x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(u32 x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
int topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 0, 2)
int lowbit(int x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(u32 x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(ll x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
int lowbit(u64 x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
template <typename T>
T kth_bit(int k) {
return T(1) << k;
}
template <typename T>
bool has_kth_bit(T x, int k) {
return x >> k & 1;
}
template <typename UINT>
struct all_bit {
struct iter {
UINT s;
iter(UINT s) : s(s) {}
int operator*() const { return lowbit(s); }
iter &operator++() {
s &= s - 1;
return *this;
}
bool operator!=(const iter) const { return s != 0; }
};
UINT s;
all_bit(UINT s) : s(s) {}
iter begin() const { return iter(s); }
iter end() const { return iter(0); }
};
template <typename UINT>
struct all_subset {
static_assert(is_unsigned<UINT>::value);
struct iter {
UINT s, t;
bool ed;
iter(UINT s) : s(s), t(s), ed(0) {}
UINT operator*() const { return s ^ t; }
iter &operator++() {
(t == 0 ? ed = 1 : t = (t - 1) & s);
return *this;
}
bool operator!=(const iter) const { return !ed; }
};
UINT s;
all_subset(UINT s) : s(s) {}
iter begin() const { return iter(s); }
iter end() const { return iter(0); }
};
template <typename T>
T floor(T a, T b) {
return a / b - (a % b && (a ^ b) < 0);
}
template <typename T>
T ceil(T x, T y) {
return floor(x + y - 1, y);
}
template <typename T>
T bmod(T x, T y) {
return x - y * floor(x, y);
}
template <typename T>
pair<T, T> divmod(T x, T y) {
T q = floor(x, y);
return {q, x - q * y};
}
constexpr ll TEN[] = {
1LL,
10LL,
100LL,
1000LL,
10000LL,
100000LL,
1000000LL,
10000000LL,
100000000LL,
1000000000LL,
10000000000LL,
100000000000LL,
1000000000000LL,
10000000000000LL,
100000000000000LL,
1000000000000000LL,
10000000000000000LL,
100000000000000000LL,
1000000000000000000LL,
};
template <typename T, typename U>
T SUM(const U &A) {
return std::accumulate(A.begin(), A.end(), T{});
}
#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
template <class C, class T>
inline long long LB(const C &c, const T &x) {
return lower_bound(c.begin(), c.end(), x) - c.begin();
}
template <class C, class T>
inline long long UB(const C &c, const T &x) {
return upper_bound(c.begin(), c.end(), x) - c.begin();
}
#define UNIQUE(x) \
sort(all(x)), x.erase(unique(all(x)), x.end()), x.shrink_to_fit()
template <typename T>
T POP(deque<T> &que) {
T a = que.front();
que.pop_front();
return a;
}
template <class T, class Container, class Compare>
T POP(priority_queue<T, Container, Compare> &que) {
T a = que.top();
que.pop();
return a;
}
template <typename T>
T POP(vc<T> &que) {
T a = que.back();
que.pop_back();
return a;
}
template <typename F>
ll binary_search(F check, ll ok, ll ng, bool check_ok = true) {
if (check_ok) assert(check(ok));
while (llabs(ok - ng) > 1) {
auto x = (ng + ok) / 2;
(check(x) ? ok : ng) = x;
}
return ok;
}
template <typename F>
double binary_search_real(F check, double ok, double ng, int iter = 100) {
FOR(iter) {
double x = (ok + ng) / 2;
(check(x) ? ok : ng) = x;
}
return (ok + ng) / 2;
}
template <class T, class S>
inline bool chmax(T &a, const S &b) {
return (a < b ? a = b, 1 : 0);
}
template <class T, class S>
inline bool chmin(T &a, const S &b) {
return (a > b ? a = b, 1 : 0);
}
// ? は -1
vc<int> s_to_vi(const string &S, char first_char) {
vc<int> A(S.size());
FOR(i, S.size()) { A[i] = (S[i] != '?' ? S[i] - first_char : -1); }
return A;
}
template <typename T, typename U>
vc<T> cumsum(const vc<U> &A, int off = 1) {
int N = A.size();
vc<T> B(N + 1);
FOR(i, N) { B[i + 1] = B[i] + A[i]; }
if (off == 0) B.erase(B.begin());
return B;
}
// stable sort
template <typename T>
vc<int> argsort(const vc<T> &A) {
vc<int> ids(len(A));
iota(all(ids), 0);
sort(all(ids),
[&](int i, int j) { return (A[i] == A[j] ? i < j : A[i] < A[j]); });
return ids;
}
// A[I[0]], A[I[1]], ...
template <typename T>
vc<T> rearrange(const vc<T> &A, const vc<int> &I) {
vc<T> B(len(I));
FOR(i, len(I)) B[i] = A[I[i]];
return B;
}
template <typename T, typename... Vectors>
void concat(vc<T> &first, const Vectors &...others) {
vc<T> &res = first;
(res.insert(res.end(), others.begin(), others.end()), ...);
}
#endif
#line 3 "test/1_mytest/decremental_fastset.test.cpp"
#line 2 "ds/unionfind/unionfind.hpp"
struct UnionFind {
int n, n_comp;
vc<int> dat; // par or (-size)
UnionFind(int n = 0) { build(n); }
void build(int m) {
n = m, n_comp = m;
dat.assign(n, -1);
}
void reset() { build(n); }
int operator[](int x) {
while (dat[x] >= 0) {
int pp = dat[dat[x]];
if (pp < 0) { return dat[x]; }
x = dat[x] = pp;
}
return x;
}
ll size(int x) {
x = (*this)[x];
return -dat[x];
}
bool merge(int x, int y) {
x = (*this)[x], y = (*this)[y];
if (x == y) return false;
if (-dat[x] < -dat[y]) swap(x, y);
dat[x] += dat[y], dat[y] = x, n_comp--;
return true;
}
vc<int> get_all() {
vc<int> A(n);
FOR(i, n) A[i] = (*this)[i];
return A;
}
};
#line 2 "random/base.hpp"
u64 RNG_64() {
static u64 x_ = u64(chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count()) * 10150724397891781847ULL;
x_ ^= x_ << 7;
return x_ ^= x_ >> 9;
}
u64 RNG(u64 lim) { return RNG_64() % lim; }
ll RNG(ll l, ll r) { return l + RNG_64() % (r - l); }
#line 2 "random/shuffle.hpp"
template <typename T>
void shuffle(vc<T>& A) {
FOR(i, len(A)) {
int j = RNG(0, i + 1);
if (i != j) swap(A[i], A[j]);
}
}
#line 1 "other/timer.hpp"
struct Timer {
bool started;
chrono::high_resolution_clock::time_point s;
Timer() : started(false) {}
void start() {
started = true;
s = chrono::high_resolution_clock::now();
}
// second from start
double operator()() {
assert(started);
chrono::high_resolution_clock::time_point t = chrono::high_resolution_clock::now();
chrono::duration<double> diff = t - s;
return diff.count();
}
};
#line 2 "ds/fastset.hpp"
// 64-ary tree
// space: (N/63) * u64
struct FastSet {
static constexpr u32 B = 64;
int n, log;
vvc<u64> seg;
FastSet() {}
FastSet(int n) { build(n); }
int size() { return n; }
template <typename F>
FastSet(int n, F f) {
build(n, f);
}
void build(int m) {
seg.clear();
n = m;
do {
seg.push_back(vc<u64>((m + B - 1) / B));
m = (m + B - 1) / B;
} while (m > 1);
log = len(seg);
}
template <typename F>
void build(int n, F f) {
build(n);
FOR(i, n) { seg[0][i / B] |= u64(f(i)) << (i % B); }
FOR(h, log - 1) {
FOR(i, len(seg[h])) { seg[h + 1][i / B] |= u64(bool(seg[h][i])) << (i % B); }
}
}
bool operator[](int i) const { return seg[0][i / B] >> (i % B) & 1; }
void insert(int i) {
assert(0 <= i && i < n);
for (int h = 0; h < log; h++) { seg[h][i / B] |= u64(1) << (i % B), i /= B; }
}
void add(int i) { insert(i); }
void erase(int i) {
assert(0 <= i && i < n);
u64 x = 0;
for (int h = 0; h < log; h++) {
seg[h][i / B] &= ~(u64(1) << (i % B));
seg[h][i / B] |= x << (i % B);
x = bool(seg[h][i / B]);
i /= B;
}
}
void remove(int i) { erase(i); }
// min[x,n) or n
int next(int i) {
assert(i <= n);
chmax(i, 0);
for (int h = 0; h < log; h++) {
if (i / B == seg[h].size()) break;
u64 d = seg[h][i / B] >> (i % B);
if (!d) {
i = i / B + 1;
continue;
}
i += lowbit(d);
for (int g = h - 1; g >= 0; g--) {
i *= B;
i += lowbit(seg[g][i / B]);
}
return i;
}
return n;
}
// max [0,x], or -1
int prev(int i) {
assert(i >= -1);
if (i >= n) i = n - 1;
for (int h = 0; h < log; h++) {
if (i == -1) break;
u64 d = seg[h][i / B] << (63 - i % B);
if (!d) {
i = i / B - 1;
continue;
}
i -= __builtin_clzll(d);
for (int g = h - 1; g >= 0; g--) {
i *= B;
i += topbit(seg[g][i / B]);
}
return i;
}
return -1;
}
bool any(int l, int r) { return next(l) < r; }
// [l, r)
template <typename F>
void enumerate(int l, int r, F f) {
for (int x = next(l); x < r; x = next(x + 1)) f(x);
}
string to_string() {
string s(n, '?');
for (int i = 0; i < n; ++i) s[i] = ((*this)[i] ? '1' : '0');
return s;
}
};
#line 2 "ds/decremental_fastset.hpp"
// amortized linear
// MoFR なしだと FastSet より遅かった
struct Decremental_FastSet {
struct Decremental_Neighbor_UF {
int n;
UnionFind uf;
vc<int> L, R;
Decremental_Neighbor_UF(int n) : n(n), uf(n + 2), L(n + 2), R(n + 2) {
FOR(i, n + 2) L[i] = i, R[i] = i;
}
void erase(int i) {
assert(0 <= i && i < n);
++i;
int l = L[uf[i - 1]], r = R[uf[i]];
uf.merge(i, i - 1);
L[uf[i]] = l, R[uf[i]] = r;
}
int prev(int i) {
assert(-1 <= i);
chmin(i, n - 1);
return L[uf[i + 1]] - 1;
}
int next(int i) {
assert(i <= n);
chmax(i, 0);
return R[uf[i]];
}
};
int N, n;
vc<u64> dat;
Decremental_Neighbor_UF X;
Decremental_FastSet(int N) : N(N), n((N + 63) / 64), X(n) {
dat.assign(n, u64(-1));
if (n) dat.back() = u64(-1) >> (64 * n - N);
}
bool operator[](int i) { return (dat[i / 64] >> (i & 63) & 1); }
void erase(int i) {
int a = i / 64, b = i & 63;
if (!(dat[a] >> b & 1)) return;
dat[a] &= ~(u64(1) << b);
if (dat[a] == 0) {
X.erase(a);
}
}
int prev(int i) {
assert(-1 <= i);
chmin(i, N - 1);
if (i == -1) return -1;
int a = i / 64, b = i & 63;
u64 x = dat[a] & (u64(-1) >> (63 - b));
if (x != 0) return 64 * a + topbit(x);
a = X.prev(a - 1);
return (a == -1 ? -1 : 64 * a + topbit(dat[a]));
}
int next(int i) {
assert(i <= N);
chmax(i, 0);
if (i == N) return N;
int a = i / 64, b = i & 63;
u64 x = dat[a] >> b;
if (x != 0) return 64 * a + b + lowbit(x);
a = X.next(a + 1);
return (a == n ? N : 64 * a + lowbit(dat[a]));
}
string to_string() {
string S(N, '.');
FOR(i, N) S[i] = '0' + (dat[i / 64] >> (i & 63) & 1);
return S;
}
};
#line 9 "test/1_mytest/decremental_fastset.test.cpp"
// ackerman. memory 多め
struct Decremental_FastSet_UF_ONLY {
int n;
UnionFind uf;
vc<int> L, R;
Decremental_FastSet_UF_ONLY(int n) : n(n), uf(n + 2), L(n + 2), R(n + 2) {
FOR(i, n + 2) L[i] = i, R[i] = i;
}
void erase(int i) {
assert(0 <= i && i < n);
++i;
int l = L[uf[i - 1]], r = R[uf[i]];
uf.merge(i, i - 1);
L[uf[i]] = l, R[uf[i]] = r;
}
int prev(int i) {
assert(-1 <= i);
chmin(i, n - 1);
return L[uf[i + 1]] - 1;
}
int next(int i) {
assert(i <= n);
chmax(i, 0);
return R[uf[i]];
}
};
vc<pair<int, int>> sol1(vc<int> A, vc<int> B) {
int N = len(A);
FastSet FS(N, [&](int i) -> int { return 1; });
vc<pair<int, int>> ANS(N);
FOR(i, N) {
FS.erase(A[i]);
ANS[i] = {FS.prev(B[i]), FS.next(B[i])};
}
return ANS;
}
vc<pair<int, int>> sol2(vc<int> A, vc<int> B) {
int N = len(A);
Decremental_FastSet FS(N);
vc<pair<int, int>> ANS(N);
FOR(i, N) {
FS.erase(A[i]);
ANS[i] = {FS.prev(B[i]), FS.next(B[i])};
}
return ANS;
}
vc<pair<int, int>> sol3(vc<int> A, vc<int> B) {
int N = len(A);
Decremental_FastSet_UF_ONLY FS(N);
vc<pair<int, int>> ANS(N);
FOR(i, N) {
FS.erase(A[i]);
ANS[i] = {FS.prev(B[i]), FS.next(B[i])};
}
return ANS;
}
void test() {
vc<double> X, Y, Z;
FOR(100) {
int N = 1 << 20;
vc<int> A(N);
FOR(i, N) A[i] = i;
shuffle(A);
vc<int> B(N);
FOR(i, N) B[i] = RNG(0, N);
vc<pair<int, int>> ANS1, ANS2, ANS3;
{
Timer timer;
timer.start();
ANS1 = sol1(A, B);
X.eb(timer());
}
{
Timer timer;
timer.start();
ANS2 = sol2(A, B);
Y.eb(timer());
}
{
Timer timer;
timer.start();
ANS3 = sol3(A, B);
Z.eb(timer());
}
// print(X.back(), Y.back(), Z.back());
assert(ANS1 == ANS2);
assert(ANS1 == ANS3);
}
// print(SUM<double>(X));
// print(SUM<double>(Y));
// print(SUM<double>(Z));
}
void solve() {
int a, b;
cin >> a >> b;
cout << a + b << "\n";
}
signed main() {
test();
solve();
}