// #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <climits>
#include <vector>
#include <queue>
#include <deque>
#include <array>
#include <list>
#include <stack>
#include <tuple>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <string>
#include <cstring>
#include <random>
#include <bitset>
#include <iomanip>
#include <iterator>
#include <functional>
#include <ctime>
#include <chrono>
#include <cctype>
#include <fstream>
#include <ranges>
#include <numeric>
#include <complex>
#include <cassert>
using namespace std;
// #pragma GCC optimize("Ofast")
// #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#define int long long
#define sz(x) ((int)(x).size())
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define pf push_front
#define ff first
#define ss second
#define unique(x) (x).erase(unique(all(x)), (x).end())
#define min3(a, b, c) min(a, min(b, c))
#define max3(a, b, c) max(a, max(b, c))
#define FOR(i, a, b) for (int i = (a); i <= (b); i++)
#define ROF(i, a, b) for (int i = (a); i >= (b); i--)
using vi = vector<int>;
using vd = vector<double>;
using vpii = vector<pair<int, int>>;
using vpdd = vector<pair<double, double>>;
using pii = pair<int, int>;
using pdd = pair<double, double>;
template <typename Container>
void PRINT(const Container& container) {
for (const auto& e : container) {
cout << e << ' ';
} cout << '\n';
}
void print_double(double ans, int num) {
cout << fixed << setprecision(num) << ans << '\n';
}
const int inf = 1e18;
const double eps = 1e-9;
const double PI = 3.141592653589793;
string alh = "abcdefghijklmnopqrstuvwxyz";
string ALH = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
class SegmentTree2D {
private:
struct Node {
map<int, Node*> children;
int value = 0;
};
Node* root;
void update(Node*& node, int x, int y, int val, int xLeft, int xRight, int yLeft, int yRight) {
if (!node) {
node = new Node();
}
if (xLeft == xRight && yLeft == yRight) {
node->value += val;
return;
}
int midX = (xLeft + xRight) / 2;
int midY = (yLeft + yRight) / 2;
if (x <= midX) {
if (y <= midY) {
update(node->children[0], x, y, val, xLeft, midX, yLeft, midY);
}
else {
update(node->children[1], x, y, val, xLeft, midX, midY + 1, yRight);
}
}
else {
if (y <= midY) {
update(node->children[2], x, y, val, midX + 1, xRight, yLeft, midY);
}
else {
update(node->children[3], x, y, val, midX + 1, xRight, midY + 1, yRight);
}
}
node->value = 0;
for (auto& [_, child] : node->children) {
if (child) {
node->value += child->value;
}
}
}
int query(Node* node, int x1, int y1, int x2, int y2, int xLeft, int xRight, int yLeft, int yRight) {
if (!node || x1 > xRight || x2 < xLeft || y1 > yRight || y2 < yLeft) {
return 0;
}
if (x1 <= xLeft && xRight <= x2 && y1 <= yLeft && yRight <= y2) {
return node->value;
}
int midX = (xLeft + xRight) / 2;
int midY = (yLeft + yRight) / 2;
int sum = 0;
sum += query(node->children[0], x1, y1, x2, y2, xLeft, midX, yLeft, midY);
sum += query(node->children[1], x1, y1, x2, y2, xLeft, midX, midY + 1, yRight);
sum += query(node->children[2], x1, y1, x2, y2, midX + 1, xRight, yLeft, midY);
sum += query(node->children[3], x1, y1, x2, y2, midX + 1, xRight, midY + 1, yRight);
return sum;
}
public:
SegmentTree2D() { root = nullptr; }
void update(int x, int y, int value) {
update(root, x, y, value, 0, inf, 0, inf);
}
int query(int x1, int y1, int x2, int y2) {
return query(root, x1, y1, x2, y2, 0, inf, 0, inf);
}
};
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
class Treap {
public:
struct TreapNode {
int value, priority;
TreapNode* left, * right;
int size;
TreapNode(int v) :
value(v), priority(rng()),
left(nullptr), right(nullptr),
size(1) {
}
};
Treap() : root(nullptr) {}
void insert(int value) {
insert(root, new TreapNode(value));
}
void remove(int value) {
remove(root, value);
}
int Count_L(int x) {
return Count_L(root, x);
}
int Count_R(int x) {
return Count_R(root, x);
}
private:
TreapNode* root;
int getSize(TreapNode* node) {
return node ? node->size : 0;
}
void updateSize(TreapNode* node) {
if (node) {
node->size = 1 + getSize(node->left) + getSize(node->right);
}
}
void split(TreapNode* node, int key, TreapNode*& left, TreapNode*& right) {
if (!node) {
left = right = nullptr;
return;
}
if (node->value <= key) {
split(node->right, key, node->right, right);
left = node;
}
else {
split(node->left, key, left, node->left);
right = node;
}
updateSize(node);
}
void merge(TreapNode*& node, TreapNode* left, TreapNode* right) {
if (!left || !right) {
node = left ? left : right;
return;
}
if (left->priority > right->priority) {
merge(left->right, left->right, right);
node = left;
}
else {
merge(right->left, left, right->left);
node = right;
}
updateSize(node);
}
void insert(TreapNode*& node, TreapNode* newNode) {
if (!node) {
node = newNode;
return;
}
if (newNode->priority > node->priority) {
split(node, newNode->value, newNode->left, newNode->right);
node = newNode;
}
else {
insert(newNode->value <= node->value ? node->left : node->right, newNode);
}
updateSize(node);
}
void remove(TreapNode*& node, int value) {
if (!node) {
return;
}
if (node->value == value) {
TreapNode* temp = node;
merge(node, node->left, node->right);
delete temp;
}
else {
remove(value < node->value ? node->left : node->right, value);
}
updateSize(node);
}
int Count_L(TreapNode* node, int x) {
if (!node) {
return 0;
}
if (node->value <= x) {
return 1 + getSize(node->left) + Count_L(node->right, x);
}
else {
return Count_L(node->left, x);
}
}
int Count_R(TreapNode* node, int x) {
if (!node) {
return 0;
}
if (node->value >= x) {
return 1 + getSize(node->right) + Count_R(node->left, x);
}
else {
return Count_R(node->right, x);
}
}
};
class SegmentTree {
public:
SegmentTree(const vector<int> a) {
n = 1;
while (n < (int)a.size()) {
n <<= 1;
}
tree.resize(2 * n);
build(a, 1, 0, n - 1);
}
void update(int pos, int W, int U) {
update(1, 0, n - 1, pos, W, U);
}
int query_L(int l, int r, int x) {
return query_L(1, 0, n - 1, l, r, x);
}
int query_R(int l, int r, int x) {
return query_R(1, 0, n - 1, l, r, x);
}
private:
int n;
vector<Treap> tree;
void build(const vector<int>& a, int v, int tl, int tr) {
if (tl == tr) {
if (tl < (int)a.size()) {
tree[v].insert(a[tl]);
}
}
else {
int tm = (tl + tr) / 2;
build(a, 2 * v, tl, tm);
build(a, 2 * v + 1, tm + 1, tr);
for (int i = tl; i <= tr; ++i) {
if (i < (int)a.size()) {
tree[v].insert(a[i]);
}
}
}
}
void update(int v, int tl, int tr, int pos, int W, int U) {
if (tl == tr) {
tree[v].remove(W);
tree[v].insert(U);
}
else {
int tm = (tl + tr) / 2;
if (pos <= tm) {
update(2 * v, tl, tm, pos, W, U);
}
else {
update(2 * v + 1, tm + 1, tr, pos, W, U);
}
tree[v].remove(W);
tree[v].insert(U);
}
}
int query_L(int v, int tl, int tr, int l, int r, int x) {
if (l > r || tl > r || tr < l) {
return 0;
}
if (tl >= l && tr <= r) {
return tree[v].Count_L(x);
}
int tm = (tl + tr) / 2;
return query_L(2 * v, tl, tm, l, min(r, tm), x) +
query_L(2 * v + 1, tm + 1, tr, max(l, tm + 1), r, x);
}
int query_R(int v, int tl, int tr, int l, int r, int x) {
if (l > r || tl > r || tr < l) {
return 0;
}
if (tl >= l && tr <= r) {
return tree[v].Count_R(x);
}
int tm = (tl + tr) / 2;
return query_R(2 * v, tl, tm, l, min(r, tm), x) +
query_R(2 * v + 1, tm + 1, tr, max(l, tm + 1), r, x);
}
};
void Solve() {
int n; cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
vector<int> base(n);
for (int i = 0; i < n; i++) {
base[i] = 0;
}
SegmentTree LAST(base);
map<int, int> last_id;
for (int i = 0; i < n; i++) {
last_id[a[i]] = -1;
}
vector<int> last(n);
for (int i = 0; i < n; i++) {
LAST.update(i, 0, last_id[a[i]]);
last[i] = 1'000'000 - last_id[a[i]];
last_id[a[i]] = i;
}
SegmentTree FUTURE(base);
map<int, int> future_id;
for (int i = 0; i < n; i++) {
future_id[a[i]] = n;
}
vector<int> future(n);
for (int i = n - 1; i >= 0; i--) {
FUTURE.update(i, 0, future_id[a[i]]);
future[i] = future_id[a[i]];
future_id[a[i]] = i;
}
vector<int> X;
for (int i = 0; i < n; i++) {
X.push_back(last[i]);
}
vector<int> Y;
for (int i = 0; i < n; i++) {
Y.push_back(future[i]);
}
vector<pair<int, int>> points;
for (int i = 0; i < n; i++) {
points.push_back({ X[i], Y[i] });
}
SegmentTree2D ST;
for (auto p : points) {
ST.update(p.first, p.second, 1);
}
map<int, set<int>> POSITIONS;
for (int i = 0; i < n; i++) {
POSITIONS[a[i]].insert(i);
}
for (int i = 0; i < n; i++) {
if (POSITIONS[a[i]].find(-1) == POSITIONS[a[i]].end()) {
POSITIONS[a[i]].insert(-1);
}
if (POSITIONS[a[i]].find(n) == POSITIONS[a[i]].end()) {
POSITIONS[a[i]].insert(n);
}
}
int q; cin >> q;
for (int i = 0; i < q; i++) {
string Type; cin >> Type;
if (Type == "!") {
int pos, val; cin >> pos >> val;
--pos;
if (a[pos] == val) {
continue;
}
if (future[pos] != n) {
LAST.update(future[pos], pos, 1'000'000 - last[pos]);
ST.update(last[future[pos]], future[future[pos]], -1);
}
if (1'000'000 - last[pos] != -1) {
FUTURE.update(1'000'000 - last[pos], pos, future[pos]);
ST.update(last[1'000'000 - last[pos]], future[1'000'000 - last[pos]], -1);
}
if (future[pos] != n) {
last[future[pos]] = last[pos];
ST.update(last[future[pos]], future[future[pos]], 1);
}
if (1'000'000 - last[pos] != -1) {
future[1'000'000 - last[pos]] = future[pos];
ST.update(last[1'000'000 - last[pos]], future[1'000'000 - last[pos]], 1);
}
ST.update(last[pos], future[pos], -1);
POSITIONS[a[pos]].erase(pos);
POSITIONS[val].insert(pos);
if (POSITIONS[val].find(-1) == POSITIONS[val].end()) {
POSITIONS[val].insert(-1);
}
if (POSITIONS[val].find(n) == POSITIONS[val].end()) {
POSITIONS[val].insert(n);
}
int Last_for_val = *(--POSITIONS[val].lower_bound(pos));
int Future_for_val = *POSITIONS[val].upper_bound(pos);
LAST.update(pos, 1'000'000 - last[pos], Last_for_val);
FUTURE.update(pos, future[pos], Future_for_val);
last[pos] = 1'000'000 - Last_for_val;
future[pos] = Future_for_val;
a[pos] = val;
ST.update(last[pos], future[pos], 1);
if (Future_for_val != n) {
LAST.update(Future_for_val, Last_for_val, pos);
ST.update(last[Future_for_val], future[Future_for_val], -1);
}
if (Last_for_val != -1) {
FUTURE.update(Last_for_val, Future_for_val, pos);
ST.update(last[Last_for_val], future[Last_for_val], -1);
}
if (Future_for_val != n) {
last[Future_for_val] = 1'000'000 - pos;
ST.update(last[Future_for_val], future[Future_for_val], 1);
}
if (Last_for_val != -1) {
future[Last_for_val] = pos;
ST.update(last[Last_for_val], future[Last_for_val], 1);
}
}
else {
int l, r; cin >> l >> r;
--l;
--r;
int min_X = 1'000'000 - l;
int min_Y = r;
cout << ST.query(min_X + 1, min_Y + 1, inf, inf) - LAST.query_L(r + 1, n - 1, l - 1) - FUTURE.query_R(0, l - 1, r + 1) << endl;
}
}
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
/*
________________
/ Just solved it \
| in my mind |
\________________/
/
/
/> フ ___________
| _ _| | |
/`ミ _x 彡 | WA 2 |
/ | |__________|
/ ヽ ノ / /
/ ̄| | | | /_________ /
| ( ̄ヽ__ヽ_)_)
\二つ
*/
/*
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
*/
// auto start = chrono::high_resolution_clock::now();
int multitest = false;
if (multitest == true) {
int ctt; cin >> ctt;
for (int i = 0; i < ctt; i++) {
Solve();
}
}
else {
Solve();
}
// auto end = chrono::high_resolution_clock::now();
/*
cout << "Time taken: "
<< chrono::duration_cast<chrono::milliseconds>(end - start).count()
<< " milliseconds" << endl;
*/
return 0;
}
Ly8gI2RlZmluZSBfQ1JUX1NFQ1VSRV9OT19XQVJOSU5HUyAKCiNpbmNsdWRlIDxpb3N0cmVhbT4gCiNpbmNsdWRlIDxhbGdvcml0aG0+IAojaW5jbHVkZSA8Y21hdGg+IAojaW5jbHVkZSA8Y2xpbWl0cz4gCiNpbmNsdWRlIDx2ZWN0b3I+IAojaW5jbHVkZSA8cXVldWU+IAojaW5jbHVkZSA8ZGVxdWU+IAojaW5jbHVkZSA8YXJyYXk+IAojaW5jbHVkZSA8bGlzdD4gCiNpbmNsdWRlIDxzdGFjaz4gCiNpbmNsdWRlIDx0dXBsZT4gCiNpbmNsdWRlIDxzZXQ+IAojaW5jbHVkZSA8dW5vcmRlcmVkX3NldD4gCiNpbmNsdWRlIDxtYXA+IAojaW5jbHVkZSA8dW5vcmRlcmVkX21hcD4gCiNpbmNsdWRlIDxzdHJpbmc+IAojaW5jbHVkZSA8Y3N0cmluZz4gCiNpbmNsdWRlIDxyYW5kb20+IAojaW5jbHVkZSA8Yml0c2V0PiAKI2luY2x1ZGUgPGlvbWFuaXA+IAojaW5jbHVkZSA8aXRlcmF0b3I+IAojaW5jbHVkZSA8ZnVuY3Rpb25hbD4gCiNpbmNsdWRlIDxjdGltZT4gCiNpbmNsdWRlIDxjaHJvbm8+IAojaW5jbHVkZSA8Y2N0eXBlPiAKI2luY2x1ZGUgPGZzdHJlYW0+IAojaW5jbHVkZSA8cmFuZ2VzPiAKI2luY2x1ZGUgPG51bWVyaWM+IAojaW5jbHVkZSA8Y29tcGxleD4gCiNpbmNsdWRlIDxjYXNzZXJ0PiAKCnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgovLyAjcHJhZ21hIEdDQyBvcHRpbWl6ZSgiT2Zhc3QiKSAKLy8gI3ByYWdtYSBHQ0MgdGFyZ2V0KCJhdngyLGJtaSxibWkyLGx6Y250LHBvcGNudCIpCgojZGVmaW5lIGludCAgICAgICAgICAgICAgIGxvbmcgbG9uZyAKI2RlZmluZSBzeih4KSAgICAgICAgICAgICAoKGludCkoeCkuc2l6ZSgpKSAKI2RlZmluZSBtcCAgICAgICAgICAgICAgICBtYWtlX3BhaXIgCiNkZWZpbmUgYWxsKHgpICAgICAgICAgICAgKHgpLmJlZ2luKCksICh4KS5lbmQoKSAKI2RlZmluZSBwYiAgICAgICAgICAgICAgICBwdXNoX2JhY2sgCiNkZWZpbmUgcGYgICAgICAgICAgICAgICAgcHVzaF9mcm9udCAKI2RlZmluZSBmZiAgICAgICAgICAgICAgICBmaXJzdCAKI2RlZmluZSBzcyAgICAgICAgICAgICAgICBzZWNvbmQgCiNkZWZpbmUgdW5pcXVlKHgpICAgICAgICAgKHgpLmVyYXNlKHVuaXF1ZShhbGwoeCkpLCAoeCkuZW5kKCkpIAojZGVmaW5lIG1pbjMoYSwgYiwgYykgICAgIG1pbihhLCBtaW4oYiwgYykpIAojZGVmaW5lIG1heDMoYSwgYiwgYykgICAgIG1heChhLCBtYXgoYiwgYykpIAojZGVmaW5lIEZPUihpLCBhLCBiKSAgICAgIGZvciAoaW50IGkgPSAoYSk7IGkgPD0gKGIpOyBpKyspIAojZGVmaW5lIFJPRihpLCBhLCBiKSAgICAgIGZvciAoaW50IGkgPSAoYSk7IGkgPj0gKGIpOyBpLS0pIAoKdXNpbmcgdmkgPSB2ZWN0b3I8aW50PjsKdXNpbmcgdmQgPSB2ZWN0b3I8ZG91YmxlPjsKdXNpbmcgdnBpaSA9IHZlY3RvcjxwYWlyPGludCwgaW50Pj47CnVzaW5nIHZwZGQgPSB2ZWN0b3I8cGFpcjxkb3VibGUsIGRvdWJsZT4+Owp1c2luZyBwaWkgPSBwYWlyPGludCwgaW50PjsKdXNpbmcgcGRkID0gcGFpcjxkb3VibGUsIGRvdWJsZT47Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgQ29udGFpbmVyPgp2b2lkIFBSSU5UKGNvbnN0IENvbnRhaW5lciYgY29udGFpbmVyKSB7CiAgICBmb3IgKGNvbnN0IGF1dG8mIGUgOiBjb250YWluZXIpIHsKICAgICAgICBjb3V0IDw8IGUgPDwgJyAnOwogICAgfSBjb3V0IDw8ICdcbic7Cn0KCnZvaWQgcHJpbnRfZG91YmxlKGRvdWJsZSBhbnMsIGludCBudW0pIHsKICAgIGNvdXQgPDwgZml4ZWQgPDwgc2V0cHJlY2lzaW9uKG51bSkgPDwgYW5zIDw8ICdcbic7Cn0KCmNvbnN0IGludCBpbmYgPSAxZTE4Owpjb25zdCBkb3VibGUgZXBzID0gMWUtOTsKY29uc3QgZG91YmxlIFBJID0gMy4xNDE1OTI2NTM1ODk3OTM7CgpzdHJpbmcgYWxoID0gImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6IjsKc3RyaW5nIEFMSCA9ICJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWiI7CgpjbGFzcyBTZWdtZW50VHJlZTJEIHsKcHJpdmF0ZToKICAgIHN0cnVjdCBOb2RlIHsKICAgICAgICBtYXA8aW50LCBOb2RlKj4gY2hpbGRyZW47CiAgICAgICAgaW50IHZhbHVlID0gMDsKICAgIH07CgogICAgTm9kZSogcm9vdDsKCiAgICB2b2lkIHVwZGF0ZShOb2RlKiYgbm9kZSwgaW50IHgsIGludCB5LCBpbnQgdmFsLCBpbnQgeExlZnQsIGludCB4UmlnaHQsIGludCB5TGVmdCwgaW50IHlSaWdodCkgewogICAgICAgIGlmICghbm9kZSkgewogICAgICAgICAgICBub2RlID0gbmV3IE5vZGUoKTsKICAgICAgICB9CgogICAgICAgIGlmICh4TGVmdCA9PSB4UmlnaHQgJiYgeUxlZnQgPT0geVJpZ2h0KSB7CiAgICAgICAgICAgIG5vZGUtPnZhbHVlICs9IHZhbDsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgaW50IG1pZFggPSAoeExlZnQgKyB4UmlnaHQpIC8gMjsKICAgICAgICBpbnQgbWlkWSA9ICh5TGVmdCArIHlSaWdodCkgLyAyOwoKICAgICAgICBpZiAoeCA8PSBtaWRYKSB7CiAgICAgICAgICAgIGlmICh5IDw9IG1pZFkpIHsKICAgICAgICAgICAgICAgIHVwZGF0ZShub2RlLT5jaGlsZHJlblswXSwgeCwgeSwgdmFsLCB4TGVmdCwgbWlkWCwgeUxlZnQsIG1pZFkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgdXBkYXRlKG5vZGUtPmNoaWxkcmVuWzFdLCB4LCB5LCB2YWwsIHhMZWZ0LCBtaWRYLCBtaWRZICsgMSwgeVJpZ2h0KTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgaWYgKHkgPD0gbWlkWSkgewogICAgICAgICAgICAgICAgdXBkYXRlKG5vZGUtPmNoaWxkcmVuWzJdLCB4LCB5LCB2YWwsIG1pZFggKyAxLCB4UmlnaHQsIHlMZWZ0LCBtaWRZKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHVwZGF0ZShub2RlLT5jaGlsZHJlblszXSwgeCwgeSwgdmFsLCBtaWRYICsgMSwgeFJpZ2h0LCBtaWRZICsgMSwgeVJpZ2h0KTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgbm9kZS0+dmFsdWUgPSAwOwogICAgICAgIGZvciAoYXV0byYgW18sIGNoaWxkXSA6IG5vZGUtPmNoaWxkcmVuKSB7CiAgICAgICAgICAgIGlmIChjaGlsZCkgewogICAgICAgICAgICAgICAgbm9kZS0+dmFsdWUgKz0gY2hpbGQtPnZhbHVlOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGludCBxdWVyeShOb2RlKiBub2RlLCBpbnQgeDEsIGludCB5MSwgaW50IHgyLCBpbnQgeTIsIGludCB4TGVmdCwgaW50IHhSaWdodCwgaW50IHlMZWZ0LCBpbnQgeVJpZ2h0KSB7CiAgICAgICAgaWYgKCFub2RlIHx8IHgxID4geFJpZ2h0IHx8IHgyIDwgeExlZnQgfHwgeTEgPiB5UmlnaHQgfHwgeTIgPCB5TGVmdCkgewogICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICB9CgogICAgICAgIGlmICh4MSA8PSB4TGVmdCAmJiB4UmlnaHQgPD0geDIgJiYgeTEgPD0geUxlZnQgJiYgeVJpZ2h0IDw9IHkyKSB7CiAgICAgICAgICAgIHJldHVybiBub2RlLT52YWx1ZTsKICAgICAgICB9CgogICAgICAgIGludCBtaWRYID0gKHhMZWZ0ICsgeFJpZ2h0KSAvIDI7CiAgICAgICAgaW50IG1pZFkgPSAoeUxlZnQgKyB5UmlnaHQpIC8gMjsKCiAgICAgICAgaW50IHN1bSA9IDA7CiAgICAgICAgc3VtICs9IHF1ZXJ5KG5vZGUtPmNoaWxkcmVuWzBdLCB4MSwgeTEsIHgyLCB5MiwgeExlZnQsIG1pZFgsIHlMZWZ0LCBtaWRZKTsKICAgICAgICBzdW0gKz0gcXVlcnkobm9kZS0+Y2hpbGRyZW5bMV0sIHgxLCB5MSwgeDIsIHkyLCB4TGVmdCwgbWlkWCwgbWlkWSArIDEsIHlSaWdodCk7CiAgICAgICAgc3VtICs9IHF1ZXJ5KG5vZGUtPmNoaWxkcmVuWzJdLCB4MSwgeTEsIHgyLCB5MiwgbWlkWCArIDEsIHhSaWdodCwgeUxlZnQsIG1pZFkpOwogICAgICAgIHN1bSArPSBxdWVyeShub2RlLT5jaGlsZHJlblszXSwgeDEsIHkxLCB4MiwgeTIsIG1pZFggKyAxLCB4UmlnaHQsIG1pZFkgKyAxLCB5UmlnaHQpOwoKICAgICAgICByZXR1cm4gc3VtOwogICAgfQoKcHVibGljOgogICAgU2VnbWVudFRyZWUyRCgpIHsgcm9vdCA9IG51bGxwdHI7IH0KCiAgICB2b2lkIHVwZGF0ZShpbnQgeCwgaW50IHksIGludCB2YWx1ZSkgewogICAgICAgIHVwZGF0ZShyb290LCB4LCB5LCB2YWx1ZSwgMCwgaW5mLCAwLCBpbmYpOwogICAgfQoKICAgIGludCBxdWVyeShpbnQgeDEsIGludCB5MSwgaW50IHgyLCBpbnQgeTIpIHsKICAgICAgICByZXR1cm4gcXVlcnkocm9vdCwgeDEsIHkxLCB4MiwgeTIsIDAsIGluZiwgMCwgaW5mKTsKICAgIH0KfTsKCm10MTk5Mzcgcm5nKGNocm9ubzo6c3RlYWR5X2Nsb2NrOjpub3coKS50aW1lX3NpbmNlX2Vwb2NoKCkuY291bnQoKSk7CgpjbGFzcyBUcmVhcCB7CnB1YmxpYzoKICAgIHN0cnVjdCBUcmVhcE5vZGUgewogICAgICAgIGludCB2YWx1ZSwgcHJpb3JpdHk7CiAgICAgICAgVHJlYXBOb2RlKiBsZWZ0LCAqIHJpZ2h0OwogICAgICAgIGludCBzaXplOwoKICAgICAgICBUcmVhcE5vZGUoaW50IHYpIDoKICAgICAgICAgICAgdmFsdWUodiksIHByaW9yaXR5KHJuZygpKSwKICAgICAgICAgICAgbGVmdChudWxscHRyKSwgcmlnaHQobnVsbHB0ciksCiAgICAgICAgICAgIHNpemUoMSkgewogICAgICAgIH0KICAgIH07CgogICAgVHJlYXAoKSA6IHJvb3QobnVsbHB0cikge30KCiAgICB2b2lkIGluc2VydChpbnQgdmFsdWUpIHsKICAgICAgICBpbnNlcnQocm9vdCwgbmV3IFRyZWFwTm9kZSh2YWx1ZSkpOwogICAgfQoKICAgIHZvaWQgcmVtb3ZlKGludCB2YWx1ZSkgewogICAgICAgIHJlbW92ZShyb290LCB2YWx1ZSk7CiAgICB9CgogICAgaW50IENvdW50X0woaW50IHgpIHsKICAgICAgICByZXR1cm4gQ291bnRfTChyb290LCB4KTsKICAgIH0KCiAgICBpbnQgQ291bnRfUihpbnQgeCkgewogICAgICAgIHJldHVybiBDb3VudF9SKHJvb3QsIHgpOwogICAgfQoKcHJpdmF0ZToKICAgIFRyZWFwTm9kZSogcm9vdDsKCiAgICBpbnQgZ2V0U2l6ZShUcmVhcE5vZGUqIG5vZGUpIHsKICAgICAgICByZXR1cm4gbm9kZSA/IG5vZGUtPnNpemUgOiAwOwogICAgfQoKICAgIHZvaWQgdXBkYXRlU2l6ZShUcmVhcE5vZGUqIG5vZGUpIHsKICAgICAgICBpZiAobm9kZSkgewogICAgICAgICAgICBub2RlLT5zaXplID0gMSArIGdldFNpemUobm9kZS0+bGVmdCkgKyBnZXRTaXplKG5vZGUtPnJpZ2h0KTsKICAgICAgICB9CiAgICB9CgogICAgdm9pZCBzcGxpdChUcmVhcE5vZGUqIG5vZGUsIGludCBrZXksIFRyZWFwTm9kZSomIGxlZnQsIFRyZWFwTm9kZSomIHJpZ2h0KSB7CiAgICAgICAgaWYgKCFub2RlKSB7CiAgICAgICAgICAgIGxlZnQgPSByaWdodCA9IG51bGxwdHI7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIGlmIChub2RlLT52YWx1ZSA8PSBrZXkpIHsKICAgICAgICAgICAgc3BsaXQobm9kZS0+cmlnaHQsIGtleSwgbm9kZS0+cmlnaHQsIHJpZ2h0KTsKICAgICAgICAgICAgbGVmdCA9IG5vZGU7CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICBzcGxpdChub2RlLT5sZWZ0LCBrZXksIGxlZnQsIG5vZGUtPmxlZnQpOwogICAgICAgICAgICByaWdodCA9IG5vZGU7CiAgICAgICAgfQoKICAgICAgICB1cGRhdGVTaXplKG5vZGUpOwogICAgfQoKICAgIHZvaWQgbWVyZ2UoVHJlYXBOb2RlKiYgbm9kZSwgVHJlYXBOb2RlKiBsZWZ0LCBUcmVhcE5vZGUqIHJpZ2h0KSB7CiAgICAgICAgaWYgKCFsZWZ0IHx8ICFyaWdodCkgewogICAgICAgICAgICBub2RlID0gbGVmdCA/IGxlZnQgOiByaWdodDsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgaWYgKGxlZnQtPnByaW9yaXR5ID4gcmlnaHQtPnByaW9yaXR5KSB7CiAgICAgICAgICAgIG1lcmdlKGxlZnQtPnJpZ2h0LCBsZWZ0LT5yaWdodCwgcmlnaHQpOwogICAgICAgICAgICBub2RlID0gbGVmdDsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIG1lcmdlKHJpZ2h0LT5sZWZ0LCBsZWZ0LCByaWdodC0+bGVmdCk7CiAgICAgICAgICAgIG5vZGUgPSByaWdodDsKICAgICAgICB9CgogICAgICAgIHVwZGF0ZVNpemUobm9kZSk7CiAgICB9CgogICAgdm9pZCBpbnNlcnQoVHJlYXBOb2RlKiYgbm9kZSwgVHJlYXBOb2RlKiBuZXdOb2RlKSB7CiAgICAgICAgaWYgKCFub2RlKSB7CiAgICAgICAgICAgIG5vZGUgPSBuZXdOb2RlOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBpZiAobmV3Tm9kZS0+cHJpb3JpdHkgPiBub2RlLT5wcmlvcml0eSkgewogICAgICAgICAgICBzcGxpdChub2RlLCBuZXdOb2RlLT52YWx1ZSwgbmV3Tm9kZS0+bGVmdCwgbmV3Tm9kZS0+cmlnaHQpOwogICAgICAgICAgICBub2RlID0gbmV3Tm9kZTsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIGluc2VydChuZXdOb2RlLT52YWx1ZSA8PSBub2RlLT52YWx1ZSA/IG5vZGUtPmxlZnQgOiBub2RlLT5yaWdodCwgbmV3Tm9kZSk7CiAgICAgICAgfQoKICAgICAgICB1cGRhdGVTaXplKG5vZGUpOwogICAgfQoKICAgIHZvaWQgcmVtb3ZlKFRyZWFwTm9kZSomIG5vZGUsIGludCB2YWx1ZSkgewogICAgICAgIGlmICghbm9kZSkgewogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBpZiAobm9kZS0+dmFsdWUgPT0gdmFsdWUpIHsKICAgICAgICAgICAgVHJlYXBOb2RlKiB0ZW1wID0gbm9kZTsKICAgICAgICAgICAgbWVyZ2Uobm9kZSwgbm9kZS0+bGVmdCwgbm9kZS0+cmlnaHQpOwogICAgICAgICAgICBkZWxldGUgdGVtcDsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIHJlbW92ZSh2YWx1ZSA8IG5vZGUtPnZhbHVlID8gbm9kZS0+bGVmdCA6IG5vZGUtPnJpZ2h0LCB2YWx1ZSk7CiAgICAgICAgfQoKICAgICAgICB1cGRhdGVTaXplKG5vZGUpOwogICAgfQoKICAgIGludCBDb3VudF9MKFRyZWFwTm9kZSogbm9kZSwgaW50IHgpIHsKICAgICAgICBpZiAoIW5vZGUpIHsKICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgfQoKICAgICAgICBpZiAobm9kZS0+dmFsdWUgPD0geCkgewogICAgICAgICAgICByZXR1cm4gMSArIGdldFNpemUobm9kZS0+bGVmdCkgKyBDb3VudF9MKG5vZGUtPnJpZ2h0LCB4KTsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBDb3VudF9MKG5vZGUtPmxlZnQsIHgpOwogICAgICAgIH0KICAgIH0KCiAgICBpbnQgQ291bnRfUihUcmVhcE5vZGUqIG5vZGUsIGludCB4KSB7CiAgICAgICAgaWYgKCFub2RlKSB7CiAgICAgICAgICAgIHJldHVybiAwOwogICAgICAgIH0KCiAgICAgICAgaWYgKG5vZGUtPnZhbHVlID49IHgpIHsKICAgICAgICAgICAgcmV0dXJuIDEgKyBnZXRTaXplKG5vZGUtPnJpZ2h0KSArIENvdW50X1Iobm9kZS0+bGVmdCwgeCk7CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICByZXR1cm4gQ291bnRfUihub2RlLT5yaWdodCwgeCk7CiAgICAgICAgfQogICAgfQp9OwoKY2xhc3MgU2VnbWVudFRyZWUgewpwdWJsaWM6CiAgICBTZWdtZW50VHJlZShjb25zdCB2ZWN0b3I8aW50PiBhKSB7CiAgICAgICAgbiA9IDE7CiAgICAgICAgd2hpbGUgKG4gPCAoaW50KWEuc2l6ZSgpKSB7CiAgICAgICAgICAgIG4gPDw9IDE7CiAgICAgICAgfQogICAgICAgIHRyZWUucmVzaXplKDIgKiBuKTsKICAgICAgICBidWlsZChhLCAxLCAwLCBuIC0gMSk7CiAgICB9CgogICAgdm9pZCB1cGRhdGUoaW50IHBvcywgaW50IFcsIGludCBVKSB7CiAgICAgICAgdXBkYXRlKDEsIDAsIG4gLSAxLCBwb3MsIFcsIFUpOwogICAgfQoKICAgIGludCBxdWVyeV9MKGludCBsLCBpbnQgciwgaW50IHgpIHsKICAgICAgICByZXR1cm4gcXVlcnlfTCgxLCAwLCBuIC0gMSwgbCwgciwgeCk7CiAgICB9CgogICAgaW50IHF1ZXJ5X1IoaW50IGwsIGludCByLCBpbnQgeCkgewogICAgICAgIHJldHVybiBxdWVyeV9SKDEsIDAsIG4gLSAxLCBsLCByLCB4KTsKICAgIH0KCnByaXZhdGU6CiAgICBpbnQgbjsKICAgIHZlY3RvcjxUcmVhcD4gdHJlZTsKCiAgICB2b2lkIGJ1aWxkKGNvbnN0IHZlY3RvcjxpbnQ+JiBhLCBpbnQgdiwgaW50IHRsLCBpbnQgdHIpIHsKICAgICAgICBpZiAodGwgPT0gdHIpIHsKICAgICAgICAgICAgaWYgKHRsIDwgKGludClhLnNpemUoKSkgewogICAgICAgICAgICAgICAgdHJlZVt2XS5pbnNlcnQoYVt0bF0pOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICBpbnQgdG0gPSAodGwgKyB0cikgLyAyOwoKICAgICAgICAgICAgYnVpbGQoYSwgMiAqIHYsIHRsLCB0bSk7CiAgICAgICAgICAgIGJ1aWxkKGEsIDIgKiB2ICsgMSwgdG0gKyAxLCB0cik7CgogICAgICAgICAgICBmb3IgKGludCBpID0gdGw7IGkgPD0gdHI7ICsraSkgewogICAgICAgICAgICAgICAgaWYgKGkgPCAoaW50KWEuc2l6ZSgpKSB7CiAgICAgICAgICAgICAgICAgICAgdHJlZVt2XS5pbnNlcnQoYVtpXSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgdm9pZCB1cGRhdGUoaW50IHYsIGludCB0bCwgaW50IHRyLCBpbnQgcG9zLCBpbnQgVywgaW50IFUpIHsKICAgICAgICBpZiAodGwgPT0gdHIpIHsKICAgICAgICAgICAgdHJlZVt2XS5yZW1vdmUoVyk7CiAgICAgICAgICAgIHRyZWVbdl0uaW5zZXJ0KFUpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgaW50IHRtID0gKHRsICsgdHIpIC8gMjsKICAgICAgICAgICAgaWYgKHBvcyA8PSB0bSkgewogICAgICAgICAgICAgICAgdXBkYXRlKDIgKiB2LCB0bCwgdG0sIHBvcywgVywgVSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICB1cGRhdGUoMiAqIHYgKyAxLCB0bSArIDEsIHRyLCBwb3MsIFcsIFUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRyZWVbdl0ucmVtb3ZlKFcpOwogICAgICAgICAgICB0cmVlW3ZdLmluc2VydChVKTsKICAgICAgICB9CiAgICB9CgogICAgaW50IHF1ZXJ5X0woaW50IHYsIGludCB0bCwgaW50IHRyLCBpbnQgbCwgaW50IHIsIGludCB4KSB7CiAgICAgICAgaWYgKGwgPiByIHx8IHRsID4gciB8fCB0ciA8IGwpIHsKICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgfQoKICAgICAgICBpZiAodGwgPj0gbCAmJiB0ciA8PSByKSB7CiAgICAgICAgICAgIHJldHVybiB0cmVlW3ZdLkNvdW50X0woeCk7CiAgICAgICAgfQoKICAgICAgICBpbnQgdG0gPSAodGwgKyB0cikgLyAyOwoKICAgICAgICByZXR1cm4gcXVlcnlfTCgyICogdiwgdGwsIHRtLCBsLCBtaW4ociwgdG0pLCB4KSArCiAgICAgICAgICAgIHF1ZXJ5X0woMiAqIHYgKyAxLCB0bSArIDEsIHRyLCBtYXgobCwgdG0gKyAxKSwgciwgeCk7CiAgICB9CgogICAgaW50IHF1ZXJ5X1IoaW50IHYsIGludCB0bCwgaW50IHRyLCBpbnQgbCwgaW50IHIsIGludCB4KSB7CiAgICAgICAgaWYgKGwgPiByIHx8IHRsID4gciB8fCB0ciA8IGwpIHsKICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgfQoKICAgICAgICBpZiAodGwgPj0gbCAmJiB0ciA8PSByKSB7CiAgICAgICAgICAgIHJldHVybiB0cmVlW3ZdLkNvdW50X1IoeCk7CiAgICAgICAgfQoKICAgICAgICBpbnQgdG0gPSAodGwgKyB0cikgLyAyOwoKICAgICAgICByZXR1cm4gcXVlcnlfUigyICogdiwgdGwsIHRtLCBsLCBtaW4ociwgdG0pLCB4KSArCiAgICAgICAgICAgIHF1ZXJ5X1IoMiAqIHYgKyAxLCB0bSArIDEsIHRyLCBtYXgobCwgdG0gKyAxKSwgciwgeCk7CiAgICB9Cn07Cgp2b2lkIFNvbHZlKCkgewogICAgaW50IG47IGNpbiA+PiBuOwoKICAgIHZlY3RvcjxpbnQ+IGEobik7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgIGNpbiA+PiBhW2ldOwogICAgfQoKICAgIHZlY3RvcjxpbnQ+IGJhc2Uobik7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgIGJhc2VbaV0gPSAwOwogICAgfQoKICAgIFNlZ21lbnRUcmVlIExBU1QoYmFzZSk7CgogICAgbWFwPGludCwgaW50PiBsYXN0X2lkOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICBsYXN0X2lkW2FbaV1dID0gLTE7CiAgICB9CgogICAgdmVjdG9yPGludD4gbGFzdChuKTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKSB7CiAgICAgICAgTEFTVC51cGRhdGUoaSwgMCwgbGFzdF9pZFthW2ldXSk7CgogICAgICAgIGxhc3RbaV0gPSAxJzAwMCcwMDAgLSBsYXN0X2lkW2FbaV1dOwogICAgICAgIGxhc3RfaWRbYVtpXV0gPSBpOwogICAgfQoKICAgIFNlZ21lbnRUcmVlIEZVVFVSRShiYXNlKTsKCiAgICBtYXA8aW50LCBpbnQ+IGZ1dHVyZV9pZDsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKSB7CiAgICAgICAgZnV0dXJlX2lkW2FbaV1dID0gbjsKICAgIH0KCiAgICB2ZWN0b3I8aW50PiBmdXR1cmUobik7CiAgICBmb3IgKGludCBpID0gbiAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICAgICAgRlVUVVJFLnVwZGF0ZShpLCAwLCBmdXR1cmVfaWRbYVtpXV0pOwoKICAgICAgICBmdXR1cmVbaV0gPSBmdXR1cmVfaWRbYVtpXV07CiAgICAgICAgZnV0dXJlX2lkW2FbaV1dID0gaTsKICAgIH0KCiAgICB2ZWN0b3I8aW50PiBYOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICBYLnB1c2hfYmFjayhsYXN0W2ldKTsKICAgIH0KCiAgICB2ZWN0b3I8aW50PiBZOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICBZLnB1c2hfYmFjayhmdXR1cmVbaV0pOwogICAgfQoKICAgIHZlY3RvcjxwYWlyPGludCwgaW50Pj4gcG9pbnRzOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICBwb2ludHMucHVzaF9iYWNrKHsgWFtpXSwgWVtpXSB9KTsKICAgIH0KCiAgICBTZWdtZW50VHJlZTJEIFNUOwogICAgZm9yIChhdXRvIHAgOiBwb2ludHMpIHsKICAgICAgICBTVC51cGRhdGUocC5maXJzdCwgcC5zZWNvbmQsIDEpOwogICAgfQoKICAgIG1hcDxpbnQsIHNldDxpbnQ+PiBQT1NJVElPTlM7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgIFBPU0lUSU9OU1thW2ldXS5pbnNlcnQoaSk7CiAgICB9CiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgIGlmIChQT1NJVElPTlNbYVtpXV0uZmluZCgtMSkgPT0gUE9TSVRJT05TW2FbaV1dLmVuZCgpKSB7CiAgICAgICAgICAgIFBPU0lUSU9OU1thW2ldXS5pbnNlcnQoLTEpOwogICAgICAgIH0KICAgICAgICBpZiAoUE9TSVRJT05TW2FbaV1dLmZpbmQobikgPT0gUE9TSVRJT05TW2FbaV1dLmVuZCgpKSB7CiAgICAgICAgICAgIFBPU0lUSU9OU1thW2ldXS5pbnNlcnQobik7CiAgICAgICAgfQogICAgfQoKICAgIGludCBxOyBjaW4gPj4gcTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgcTsgaSsrKSB7CiAgICAgICAgc3RyaW5nIFR5cGU7IGNpbiA+PiBUeXBlOwoKICAgICAgICBpZiAoVHlwZSA9PSAiISIpIHsKICAgICAgICAgICAgaW50IHBvcywgdmFsOyBjaW4gPj4gcG9zID4+IHZhbDsKCiAgICAgICAgICAgIC0tcG9zOwoKICAgICAgICAgICAgaWYgKGFbcG9zXSA9PSB2YWwpIHsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiAoZnV0dXJlW3Bvc10gIT0gbikgewogICAgICAgICAgICAgICAgTEFTVC51cGRhdGUoZnV0dXJlW3Bvc10sIHBvcywgMScwMDAnMDAwIC0gbGFzdFtwb3NdKTsKICAgICAgICAgICAgICAgIFNULnVwZGF0ZShsYXN0W2Z1dHVyZVtwb3NdXSwgZnV0dXJlW2Z1dHVyZVtwb3NdXSwgLTEpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICgxJzAwMCcwMDAgLSBsYXN0W3Bvc10gIT0gLTEpIHsKICAgICAgICAgICAgICAgIEZVVFVSRS51cGRhdGUoMScwMDAnMDAwIC0gbGFzdFtwb3NdLCBwb3MsIGZ1dHVyZVtwb3NdKTsKICAgICAgICAgICAgICAgIFNULnVwZGF0ZShsYXN0WzEnMDAwJzAwMCAtIGxhc3RbcG9zXV0sIGZ1dHVyZVsxJzAwMCcwMDAgLSBsYXN0W3Bvc11dLCAtMSk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChmdXR1cmVbcG9zXSAhPSBuKSB7CiAgICAgICAgICAgICAgICBsYXN0W2Z1dHVyZVtwb3NdXSA9IGxhc3RbcG9zXTsKICAgICAgICAgICAgICAgIFNULnVwZGF0ZShsYXN0W2Z1dHVyZVtwb3NdXSwgZnV0dXJlW2Z1dHVyZVtwb3NdXSwgMSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKDEnMDAwJzAwMCAtIGxhc3RbcG9zXSAhPSAtMSkgewogICAgICAgICAgICAgICAgZnV0dXJlWzEnMDAwJzAwMCAtIGxhc3RbcG9zXV0gPSBmdXR1cmVbcG9zXTsKICAgICAgICAgICAgICAgIFNULnVwZGF0ZShsYXN0WzEnMDAwJzAwMCAtIGxhc3RbcG9zXV0sIGZ1dHVyZVsxJzAwMCcwMDAgLSBsYXN0W3Bvc11dLCAxKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgU1QudXBkYXRlKGxhc3RbcG9zXSwgZnV0dXJlW3Bvc10sIC0xKTsKCiAgICAgICAgICAgIFBPU0lUSU9OU1thW3Bvc11dLmVyYXNlKHBvcyk7CiAgICAgICAgICAgIFBPU0lUSU9OU1t2YWxdLmluc2VydChwb3MpOwoKICAgICAgICAgICAgaWYgKFBPU0lUSU9OU1t2YWxdLmZpbmQoLTEpID09IFBPU0lUSU9OU1t2YWxdLmVuZCgpKSB7CiAgICAgICAgICAgICAgICBQT1NJVElPTlNbdmFsXS5pbnNlcnQoLTEpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChQT1NJVElPTlNbdmFsXS5maW5kKG4pID09IFBPU0lUSU9OU1t2YWxdLmVuZCgpKSB7CiAgICAgICAgICAgICAgICBQT1NJVElPTlNbdmFsXS5pbnNlcnQobik7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGludCBMYXN0X2Zvcl92YWwgPSAqKC0tUE9TSVRJT05TW3ZhbF0ubG93ZXJfYm91bmQocG9zKSk7CiAgICAgICAgICAgIGludCBGdXR1cmVfZm9yX3ZhbCA9ICpQT1NJVElPTlNbdmFsXS51cHBlcl9ib3VuZChwb3MpOwoKICAgICAgICAgICAgTEFTVC51cGRhdGUocG9zLCAxJzAwMCcwMDAgLSBsYXN0W3Bvc10sIExhc3RfZm9yX3ZhbCk7CiAgICAgICAgICAgIEZVVFVSRS51cGRhdGUocG9zLCBmdXR1cmVbcG9zXSwgRnV0dXJlX2Zvcl92YWwpOwoKICAgICAgICAgICAgbGFzdFtwb3NdID0gMScwMDAnMDAwIC0gTGFzdF9mb3JfdmFsOwogICAgICAgICAgICBmdXR1cmVbcG9zXSA9IEZ1dHVyZV9mb3JfdmFsOwoKICAgICAgICAgICAgYVtwb3NdID0gdmFsOwoKICAgICAgICAgICAgU1QudXBkYXRlKGxhc3RbcG9zXSwgZnV0dXJlW3Bvc10sIDEpOwoKICAgICAgICAgICAgaWYgKEZ1dHVyZV9mb3JfdmFsICE9IG4pIHsKICAgICAgICAgICAgICAgIExBU1QudXBkYXRlKEZ1dHVyZV9mb3JfdmFsLCBMYXN0X2Zvcl92YWwsIHBvcyk7CiAgICAgICAgICAgICAgICBTVC51cGRhdGUobGFzdFtGdXR1cmVfZm9yX3ZhbF0sIGZ1dHVyZVtGdXR1cmVfZm9yX3ZhbF0sIC0xKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoTGFzdF9mb3JfdmFsICE9IC0xKSB7CiAgICAgICAgICAgICAgICBGVVRVUkUudXBkYXRlKExhc3RfZm9yX3ZhbCwgRnV0dXJlX2Zvcl92YWwsIHBvcyk7CiAgICAgICAgICAgICAgICBTVC51cGRhdGUobGFzdFtMYXN0X2Zvcl92YWxdLCBmdXR1cmVbTGFzdF9mb3JfdmFsXSwgLTEpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiAoRnV0dXJlX2Zvcl92YWwgIT0gbikgewogICAgICAgICAgICAgICAgbGFzdFtGdXR1cmVfZm9yX3ZhbF0gPSAxJzAwMCcwMDAgLSBwb3M7CiAgICAgICAgICAgICAgICBTVC51cGRhdGUobGFzdFtGdXR1cmVfZm9yX3ZhbF0sIGZ1dHVyZVtGdXR1cmVfZm9yX3ZhbF0sIDEpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChMYXN0X2Zvcl92YWwgIT0gLTEpIHsKICAgICAgICAgICAgICAgIGZ1dHVyZVtMYXN0X2Zvcl92YWxdID0gcG9zOwogICAgICAgICAgICAgICAgU1QudXBkYXRlKGxhc3RbTGFzdF9mb3JfdmFsXSwgZnV0dXJlW0xhc3RfZm9yX3ZhbF0sIDEpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICBpbnQgbCwgcjsgY2luID4+IGwgPj4gcjsKCiAgICAgICAgICAgIC0tbDsKICAgICAgICAgICAgLS1yOwoKICAgICAgICAgICAgaW50IG1pbl9YID0gMScwMDAnMDAwIC0gbDsKICAgICAgICAgICAgaW50IG1pbl9ZID0gcjsKCiAgICAgICAgICAgIGNvdXQgPDwgU1QucXVlcnkobWluX1ggKyAxLCBtaW5fWSArIDEsIGluZiwgaW5mKSAtIExBU1QucXVlcnlfTChyICsgMSwgbiAtIDEsIGwgLSAxKSAtIEZVVFVSRS5xdWVyeV9SKDAsIGwgLSAxLCByICsgMSkgPDwgZW5kbDsKICAgICAgICB9CiAgICB9Cn0KCnNpZ25lZCBtYWluKCkgewogICAgaW9zX2Jhc2U6OnN5bmNfd2l0aF9zdGRpbyhmYWxzZSk7CiAgICBjaW4udGllKDApOwogICAgY291dC50aWUoMCk7CgogICAgLyoKICAgICAgICAgICAgICAgICAgICAgIF9fX19fX19fX19fX19fX18KICAgICAgICAgICAgICAgICAgICAgLyBKdXN0IHNvbHZlZCBpdCBcCiAgICAgICAgICAgICAgICAgICAgIHwgICBpbiBteSBtaW5kICAgfAogICAgICAgICAgICAgICAgICAgICBcX19fX19fX19fX19fX19fXy8KICAgICAgICAgICAgICAgICAgICAvCiAgICAgICAgICAgICAgICAgICAvCuOAgOOAgOOAgOOAgOOAgO+8j++8nuOAgCDjg5UgICAgICAgICBfX19fX19fX19fXwrjgIDjgIDjgIDjgIDjgIB8IOOAgF/jgIAgX3wgICAgICAgfCAgICAgICAgICB8CuOAgCDjgIDjgIDjgIDvvI9g44OfIF94IOW9oSAgICAgICB8ICAgV0EgMiAgIHwK44CA44CAIOOAgCAv44CA44CA44CAIOOAgCB8ICAgICAgIHxfX19fX19fX19ffArjgIDjgIDjgIAgL+OAgCDjg73jgIDjgIAg776JICAgICAgICAvICAgICAgICAgIC8K44CA77yP77+jfOOAgOOAgCB844CAfOOAgHwgICAgICAgL19fX19fX19fXyAvCuOAgHwgKO+/o+ODve+8v1/jg71fKV8pCuOAgO+8vOS6jOOBpAoKICAgICovCgogICAgLyoKICAgIGZyZW9wZW4oImlucHV0LnR4dCIsICJyIiwgc3RkaW4pOwogICAgZnJlb3Blbigib3V0cHV0LnR4dCIsICJ3Iiwgc3Rkb3V0KTsKICAgICovCgogICAgLy8gYXV0byBzdGFydCA9IGNocm9ubzo6aGlnaF9yZXNvbHV0aW9uX2Nsb2NrOjpub3coKTsKCiAgICBpbnQgbXVsdGl0ZXN0ID0gZmFsc2U7CiAgICBpZiAobXVsdGl0ZXN0ID09IHRydWUpIHsKICAgICAgICBpbnQgY3R0OyBjaW4gPj4gY3R0OwoKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGN0dDsgaSsrKSB7CiAgICAgICAgICAgIFNvbHZlKCk7CiAgICAgICAgfQogICAgfQogICAgZWxzZSB7CiAgICAgICAgU29sdmUoKTsKICAgIH0KCiAgICAvLyBhdXRvIGVuZCA9IGNocm9ubzo6aGlnaF9yZXNvbHV0aW9uX2Nsb2NrOjpub3coKTsKCiAgICAvKgogICAgY291dCA8PCAiVGltZSB0YWtlbjogIgogICAgICAgICA8PCBjaHJvbm86OmR1cmF0aW9uX2Nhc3Q8Y2hyb25vOjptaWxsaXNlY29uZHM+KGVuZCAtIHN0YXJ0KS5jb3VudCgpCiAgICAgICAgIDw8ICIgbWlsbGlzZWNvbmRzIiA8PCBlbmRsOwogICAgKi8KCiAgICByZXR1cm4gMDsKfQ==