// #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);
}
};
class Treap_to_Find {
public:
struct Node {
int x, y;
int count;
int size;
Node* left;
Node* right;
Node(int x, int y) :
x(x), y(y), count(1), size(1),
left(nullptr), right(nullptr) {
}
};
Treap_to_Find() : root(nullptr) {}
void Add(int x) {
root = insert(root, x, rand());
}
void Del(int x) {
root = delete_key(root, x);
}
bool Find(int x) {
return exists(root, x);
}
int Find_ll(int x) {
ans_ll = -1;
find_ll(root, x);
return ans_ll;
}
int Find_lr(int x) {
ans_lr = -1;
find_lr(root, x);
return ans_lr;
}
int Find_rl(int x) {
ans_rl = -1;
find_rl(root, x);
return ans_rl;
}
int Find_rr(int x) {
ans_rr = -1;
find_rr(root, x);
return ans_rr;
}
private:
Node* root;
int ans_ll, ans_lr, ans_rl, ans_rr;
int get_size(Node* a) {
return a ? a->size : 0;
}
void update_size(Node* a) {
if (a) {
a->size = get_size(a->left) + get_size(a->right) + a->count;
}
}
pair<Node*, Node*> split(Node* a, int k) {
if (!a) {
return { nullptr, nullptr };
}
if (a->x < k) {
pair<Node*, Node*> lr = split(a->right, k);
a->right = lr.first;
update_size(a);
return { a, lr.second };
}
else {
pair<Node*, Node*> lr = split(a->left, k);
a->left = lr.second;
update_size(a);
return { lr.first, a };
}
}
Node* merge(Node* a, Node* b) {
if (!a) return b;
if (!b) return a;
if (a->y > b->y) {
a->right = merge(a->right, b);
update_size(a);
return a;
}
else {
b->left = merge(a, b->left);
update_size(b);
return b;
}
}
Node* insert(Node* a, int x, int y) {
pair<Node*, Node*> lr = split(a, x);
Node* l = lr.first;
Node* r = lr.second;
if (l && l->x == x) {
l->count++;
update_size(l);
return merge(l, r);
}
Node* new_node = new Node(x, y);
return merge(merge(l, new_node), r);
}
Node* delete_key(Node* a, int x) {
if (!a) return nullptr;
if (a->x == x) {
if (a->count > 1) {
a->count--;
update_size(a);
return a;
}
else {
return merge(a->left, a->right);
}
}
if (x < a->x) {
a->left = delete_key(a->left, x);
}
else {
a->right = delete_key(a->right, x);
}
update_size(a);
return a;
}
bool exists(Node* a, int x) {
if (!a) {
return false;
}
if (a->x == x) {
return true;
}
if (x < a->x) {
return exists(a->left, x);
}
else {
return exists(a->right, x);
}
}
void find_ll(Node* a, int x) {
if (!a) return;
if (a->x < x) {
ans_ll = a->x;
find_ll(a->right, x);
}
else {
find_ll(a->left, x);
}
}
void find_lr(Node* a, int x) {
if (!a) return;
if (a->x <= x) {
ans_lr = a->x;
find_lr(a->right, x);
}
else {
find_lr(a->left, x);
}
}
void find_rl(Node* a, int x) {
if (!a) return;
if (a->x >= x) {
ans_rl = a->x;
find_rl(a->left, x);
}
else {
find_rl(a->right, x);
}
}
void find_rr(Node* a, int x) {
if (!a) return;
if (a->x > x) {
ans_rr = a->x;
find_rr(a->left, x);
}
else {
find_rr(a->right, 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, Treap_to_Find> POSITIONS;
for (int i = 0; i < n; i++) {
POSITIONS[a[i]].Add(i);
}
for (int i = 0; i < n; i++) {
if (POSITIONS[a[i]].Find(-1) == false) {
POSITIONS[a[i]].Add(-1);
}
if (POSITIONS[a[i]].Find(n) == false) {
POSITIONS[a[i]].Add(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]].Del(pos);
POSITIONS[val].Add(pos);
if (POSITIONS[val].Find(-1) == false) {
POSITIONS[val].Add(-1);
}
if (POSITIONS[val].Find(n) == false) {
POSITIONS[val].Add(n);
}
int Last_for_val = POSITIONS[val].Find_ll(pos);
int Future_for_val = POSITIONS[val].Find_rr(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 - POSITIONS[val].Find_ll(pos);
future[pos] = POSITIONS[val].Find_rr(pos);
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+JiBhLCBpbnQgdiwgaW50IHRsLCBpbnQgdHIpIHsKICAgICAgICBpZiAodGwgPT0gdHIpIHsKICAgICAgICAgICAgaWYgKHRsIDwgKGludClhLnNpemUoKSkgewogICAgICAgICAgICAgICAgdHJlZVt2XS5pbnNlcnQoYVt0bF0pOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICBpbnQgdG0gPSAodGwgKyB0cikgLyAyOwoKICAgICAgICAgICAgYnVpbGQoYSwgMiAqIHYsIHRsLCB0bSk7CiAgICAgICAgICAgIGJ1aWxkKGEsIDIgKiB2ICsgMSwgdG0gKyAxLCB0cik7CgogICAgICAgICAgICBmb3IgKGludCBpID0gdGw7IGkgPD0gdHI7ICsraSkgewogICAgICAgICAgICAgICAgaWYgKGkgPCAoaW50KWEuc2l6ZSgpKSB7CiAgICAgICAgICAgICAgICAgICAgdHJlZVt2XS5pbnNlcnQoYVtpXSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgdm9pZCB1cGRhdGUoaW50IHYsIGludCB0bCwgaW50IHRyLCBpbnQgcG9zLCBpbnQgVywgaW50IFUpIHsKICAgICAgICBpZiAodGwgPT0gdHIpIHsKICAgICAgICAgICAgdHJlZVt2XS5yZW1vdmUoVyk7CiAgICAgICAgICAgIHRyZWVbdl0uaW5zZXJ0KFUpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgaW50IHRtID0gKHRsICsgdHIpIC8gMjsKICAgICAgICAgICAgaWYgKHBvcyA8PSB0bSkgewogICAgICAgICAgICAgICAgdXBkYXRlKDIgKiB2LCB0bCwgdG0sIHBvcywgVywgVSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICB1cGRhdGUoMiAqIHYgKyAxLCB0bSArIDEsIHRyLCBwb3MsIFcsIFUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRyZWVbdl0ucmVtb3ZlKFcpOwogICAgICAgICAgICB0cmVlW3ZdLmluc2VydChVKTsKICAgICAgICB9CiAgICB9CgogICAgaW50IHF1ZXJ5X0woaW50IHYsIGludCB0bCwgaW50IHRyLCBpbnQgbCwgaW50IHIsIGludCB4KSB7CiAgICAgICAgaWYgKGwgPiByIHx8IHRsID4gciB8fCB0ciA8IGwpIHsKICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgfQoKICAgICAgICBpZiAodGwgPj0gbCAmJiB0ciA8PSByKSB7CiAgICAgICAgICAgIHJldHVybiB0cmVlW3ZdLkNvdW50X0woeCk7CiAgICAgICAgfQoKICAgICAgICBpbnQgdG0gPSAodGwgKyB0cikgLyAyOwoKICAgICAgICByZXR1cm4gcXVlcnlfTCgyICogdiwgdGwsIHRtLCBsLCBtaW4ociwgdG0pLCB4KSArCiAgICAgICAgICAgIHF1ZXJ5X0woMiAqIHYgKyAxLCB0bSArIDEsIHRyLCBtYXgobCwgdG0gKyAxKSwgciwgeCk7CiAgICB9CgogICAgaW50IHF1ZXJ5X1IoaW50IHYsIGludCB0bCwgaW50IHRyLCBpbnQgbCwgaW50IHIsIGludCB4KSB7CiAgICAgICAgaWYgKGwgPiByIHx8IHRsID4gciB8fCB0ciA8IGwpIHsKICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgfQoKICAgICAgICBpZiAodGwgPj0gbCAmJiB0ciA8PSByKSB7CiAgICAgICAgICAgIHJldHVybiB0cmVlW3ZdLkNvdW50X1IoeCk7CiAgICAgICAgfQoKICAgICAgICBpbnQgdG0gPSAodGwgKyB0cikgLyAyOwoKICAgICAgICByZXR1cm4gcXVlcnlfUigyICogdiwgdGwsIHRtLCBsLCBtaW4ociwgdG0pLCB4KSArCiAgICAgICAgICAgIHF1ZXJ5X1IoMiAqIHYgKyAxLCB0bSArIDEsIHRyLCBtYXgobCwgdG0gKyAxKSwgciwgeCk7CiAgICB9Cn07CgpjbGFzcyBUcmVhcF90b19GaW5kIHsKcHVibGljOgogICAgc3RydWN0IE5vZGUgewogICAgICAgIGludCB4LCB5OwoKICAgICAgICBpbnQgY291bnQ7CiAgICAgICAgaW50IHNpemU7CgogICAgICAgIE5vZGUqIGxlZnQ7CiAgICAgICAgTm9kZSogcmlnaHQ7CgogICAgICAgIE5vZGUoaW50IHgsIGludCB5KSA6CiAgICAgICAgICAgIHgoeCksIHkoeSksIGNvdW50KDEpLCBzaXplKDEpLAogICAgICAgICAgICBsZWZ0KG51bGxwdHIpLCByaWdodChudWxscHRyKSB7CiAgICAgICAgfQogICAgfTsKCiAgICBUcmVhcF90b19GaW5kKCkgOiByb290KG51bGxwdHIpIHt9CgogICAgdm9pZCBBZGQoaW50IHgpIHsKICAgICAgICByb290ID0gaW5zZXJ0KHJvb3QsIHgsIHJhbmQoKSk7CiAgICB9CgogICAgdm9pZCBEZWwoaW50IHgpIHsKICAgICAgICByb290ID0gZGVsZXRlX2tleShyb290LCB4KTsKICAgIH0KCiAgICBib29sIEZpbmQoaW50IHgpIHsKICAgICAgICByZXR1cm4gZXhpc3RzKHJvb3QsIHgpOwogICAgfQoKICAgIGludCBGaW5kX2xsKGludCB4KSB7CiAgICAgICAgYW5zX2xsID0gLTE7CiAgICAgICAgZmluZF9sbChyb290LCB4KTsKICAgICAgICByZXR1cm4gYW5zX2xsOwogICAgfQoKICAgIGludCBGaW5kX2xyKGludCB4KSB7CiAgICAgICAgYW5zX2xyID0gLTE7CiAgICAgICAgZmluZF9scihyb290LCB4KTsKICAgICAgICByZXR1cm4gYW5zX2xyOwogICAgfQoKICAgIGludCBGaW5kX3JsKGludCB4KSB7CiAgICAgICAgYW5zX3JsID0gLTE7CiAgICAgICAgZmluZF9ybChyb290LCB4KTsKICAgICAgICByZXR1cm4gYW5zX3JsOwogICAgfQoKICAgIGludCBGaW5kX3JyKGludCB4KSB7CiAgICAgICAgYW5zX3JyID0gLTE7CiAgICAgICAgZmluZF9ycihyb290LCB4KTsKICAgICAgICByZXR1cm4gYW5zX3JyOwogICAgfQoKcHJpdmF0ZToKICAgIE5vZGUqIHJvb3Q7CiAgICBpbnQgYW5zX2xsLCBhbnNfbHIsIGFuc19ybCwgYW5zX3JyOwoKICAgIGludCBnZXRfc2l6ZShOb2RlKiBhKSB7CiAgICAgICAgcmV0dXJuIGEgPyBhLT5zaXplIDogMDsKICAgIH0KCiAgICB2b2lkIHVwZGF0ZV9zaXplKE5vZGUqIGEpIHsKICAgICAgICBpZiAoYSkgewogICAgICAgICAgICBhLT5zaXplID0gZ2V0X3NpemUoYS0+bGVmdCkgKyBnZXRfc2l6ZShhLT5yaWdodCkgKyBhLT5jb3VudDsKICAgICAgICB9CiAgICB9CgogICAgcGFpcjxOb2RlKiwgTm9kZSo+IHNwbGl0KE5vZGUqIGEsIGludCBrKSB7CiAgICAgICAgaWYgKCFhKSB7CiAgICAgICAgICAgIHJldHVybiB7IG51bGxwdHIsIG51bGxwdHIgfTsKICAgICAgICB9CiAgICAgICAgaWYgKGEtPnggPCBrKSB7CiAgICAgICAgICAgIHBhaXI8Tm9kZSosIE5vZGUqPiBsciA9IHNwbGl0KGEtPnJpZ2h0LCBrKTsKICAgICAgICAgICAgYS0+cmlnaHQgPSBsci5maXJzdDsKICAgICAgICAgICAgdXBkYXRlX3NpemUoYSk7CiAgICAgICAgICAgIHJldHVybiB7IGEsIGxyLnNlY29uZCB9OwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgcGFpcjxOb2RlKiwgTm9kZSo+IGxyID0gc3BsaXQoYS0+bGVmdCwgayk7CiAgICAgICAgICAgIGEtPmxlZnQgPSBsci5zZWNvbmQ7CiAgICAgICAgICAgIHVwZGF0ZV9zaXplKGEpOwogICAgICAgICAgICByZXR1cm4geyBsci5maXJzdCwgYSB9OwogICAgICAgIH0KICAgIH0KCiAgICBOb2RlKiBtZXJnZShOb2RlKiBhLCBOb2RlKiBiKSB7CiAgICAgICAgaWYgKCFhKSByZXR1cm4gYjsKICAgICAgICBpZiAoIWIpIHJldHVybiBhOwogICAgICAgIGlmIChhLT55ID4gYi0+eSkgewogICAgICAgICAgICBhLT5yaWdodCA9IG1lcmdlKGEtPnJpZ2h0LCBiKTsKICAgICAgICAgICAgdXBkYXRlX3NpemUoYSk7CiAgICAgICAgICAgIHJldHVybiBhOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgYi0+bGVmdCA9IG1lcmdlKGEsIGItPmxlZnQpOwogICAgICAgICAgICB1cGRhdGVfc2l6ZShiKTsKICAgICAgICAgICAgcmV0dXJuIGI7CiAgICAgICAgfQogICAgfQoKICAgIE5vZGUqIGluc2VydChOb2RlKiBhLCBpbnQgeCwgaW50IHkpIHsKICAgICAgICBwYWlyPE5vZGUqLCBOb2RlKj4gbHIgPSBzcGxpdChhLCB4KTsKICAgICAgICBOb2RlKiBsID0gbHIuZmlyc3Q7CiAgICAgICAgTm9kZSogciA9IGxyLnNlY29uZDsKCiAgICAgICAgaWYgKGwgJiYgbC0+eCA9PSB4KSB7CiAgICAgICAgICAgIGwtPmNvdW50Kys7CiAgICAgICAgICAgIHVwZGF0ZV9zaXplKGwpOwogICAgICAgICAgICByZXR1cm4gbWVyZ2UobCwgcik7CiAgICAgICAgfQoKICAgICAgICBOb2RlKiBuZXdfbm9kZSA9IG5ldyBOb2RlKHgsIHkpOwogICAgICAgIHJldHVybiBtZXJnZShtZXJnZShsLCBuZXdfbm9kZSksIHIpOwogICAgfQoKICAgIE5vZGUqIGRlbGV0ZV9rZXkoTm9kZSogYSwgaW50IHgpIHsKICAgICAgICBpZiAoIWEpIHJldHVybiBudWxscHRyOwoKICAgICAgICBpZiAoYS0+eCA9PSB4KSB7CiAgICAgICAgICAgIGlmIChhLT5jb3VudCA+IDEpIHsKICAgICAgICAgICAgICAgIGEtPmNvdW50LS07CiAgICAgICAgICAgICAgICB1cGRhdGVfc2l6ZShhKTsKICAgICAgICAgICAgICAgIHJldHVybiBhOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgcmV0dXJuIG1lcmdlKGEtPmxlZnQsIGEtPnJpZ2h0KTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgaWYgKHggPCBhLT54KSB7CiAgICAgICAgICAgIGEtPmxlZnQgPSBkZWxldGVfa2V5KGEtPmxlZnQsIHgpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgYS0+cmlnaHQgPSBkZWxldGVfa2V5KGEtPnJpZ2h0LCB4KTsKICAgICAgICB9CgogICAgICAgIHVwZGF0ZV9zaXplKGEpOwogICAgICAgIHJldHVybiBhOwogICAgfQoKICAgIGJvb2wgZXhpc3RzKE5vZGUqIGEsIGludCB4KSB7CiAgICAgICAgaWYgKCFhKSB7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKGEtPnggPT0geCkgewogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgaWYgKHggPCBhLT54KSB7CiAgICAgICAgICAgIHJldHVybiBleGlzdHMoYS0+bGVmdCwgeCk7CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICByZXR1cm4gZXhpc3RzKGEtPnJpZ2h0LCB4KTsKICAgICAgICB9CiAgICB9CgogICAgdm9pZCBmaW5kX2xsKE5vZGUqIGEsIGludCB4KSB7CiAgICAgICAgaWYgKCFhKSByZXR1cm47CiAgICAgICAgaWYgKGEtPnggPCB4KSB7CiAgICAgICAgICAgIGFuc19sbCA9IGEtPng7CiAgICAgICAgICAgIGZpbmRfbGwoYS0+cmlnaHQsIHgpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgZmluZF9sbChhLT5sZWZ0LCB4KTsKICAgICAgICB9CiAgICB9CgogICAgdm9pZCBmaW5kX2xyKE5vZGUqIGEsIGludCB4KSB7CiAgICAgICAgaWYgKCFhKSByZXR1cm47CiAgICAgICAgaWYgKGEtPnggPD0geCkgewogICAgICAgICAgICBhbnNfbHIgPSBhLT54OwogICAgICAgICAgICBmaW5kX2xyKGEtPnJpZ2h0LCB4KTsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIGZpbmRfbHIoYS0+bGVmdCwgeCk7CiAgICAgICAgfQogICAgfQoKICAgIHZvaWQgZmluZF9ybChOb2RlKiBhLCBpbnQgeCkgewogICAgICAgIGlmICghYSkgcmV0dXJuOwogICAgICAgIGlmIChhLT54ID49IHgpIHsKICAgICAgICAgICAgYW5zX3JsID0gYS0+eDsKICAgICAgICAgICAgZmluZF9ybChhLT5sZWZ0LCB4KTsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIGZpbmRfcmwoYS0+cmlnaHQsIHgpOwogICAgICAgIH0KICAgIH0KCiAgICB2b2lkIGZpbmRfcnIoTm9kZSogYSwgaW50IHgpIHsKICAgICAgICBpZiAoIWEpIHJldHVybjsKICAgICAgICBpZiAoYS0+eCA+IHgpIHsKICAgICAgICAgICAgYW5zX3JyID0gYS0+eDsKICAgICAgICAgICAgZmluZF9ycihhLT5sZWZ0LCB4KTsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIGZpbmRfcnIoYS0+cmlnaHQsIHgpOwogICAgICAgIH0KICAgIH0KfTsKCnZvaWQgU29sdmUoKSB7CiAgICBpbnQgbjsgY2luID4+IG47CgogICAgdmVjdG9yPGludD4gYShuKTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKSB7CiAgICAgICAgY2luID4+IGFbaV07CiAgICB9CgogICAgdmVjdG9yPGludD4gYmFzZShuKTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKSB7CiAgICAgICAgYmFzZVtpXSA9IDA7CiAgICB9CgogICAgU2VnbWVudFRyZWUgTEFTVChiYXNlKTsKCiAgICBtYXA8aW50LCBpbnQ+IGxhc3RfaWQ7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgIGxhc3RfaWRbYVtpXV0gPSAtMTsKICAgIH0KCiAgICB2ZWN0b3I8aW50PiBsYXN0KG4pOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICBMQVNULnVwZGF0ZShpLCAwLCBsYXN0X2lkW2FbaV1dKTsKCiAgICAgICAgbGFzdFtpXSA9IDEnMDAwJzAwMCAtIGxhc3RfaWRbYVtpXV07CiAgICAgICAgbGFzdF9pZFthW2ldXSA9IGk7CiAgICB9CgogICAgU2VnbWVudFRyZWUgRlVUVVJFKGJhc2UpOwoKICAgIG1hcDxpbnQsIGludD4gZnV0dXJlX2lkOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICBmdXR1cmVfaWRbYVtpXV0gPSBuOwogICAgfQoKICAgIHZlY3RvcjxpbnQ+IGZ1dHVyZShuKTsKICAgIGZvciAoaW50IGkgPSBuIC0gMTsgaSA+PSAwOyBpLS0pIHsKICAgICAgICBGVVRVUkUudXBkYXRlKGksIDAsIGZ1dHVyZV9pZFthW2ldXSk7CgogICAgICAgIGZ1dHVyZVtpXSA9IGZ1dHVyZV9pZFthW2ldXTsKICAgICAgICBmdXR1cmVfaWRbYVtpXV0gPSBpOwogICAgfQoKICAgIHZlY3RvcjxpbnQ+IFg7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgIFgucHVzaF9iYWNrKGxhc3RbaV0pOwogICAgfQoKICAgIHZlY3RvcjxpbnQ+IFk7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgIFkucHVzaF9iYWNrKGZ1dHVyZVtpXSk7CiAgICB9CgogICAgdmVjdG9yPHBhaXI8aW50LCBpbnQ+PiBwb2ludHM7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgIHBvaW50cy5wdXNoX2JhY2soeyBYW2ldLCBZW2ldIH0pOwogICAgfQoKICAgIFNlZ21lbnRUcmVlMkQgU1Q7CiAgICBmb3IgKGF1dG8gcCA6IHBvaW50cykgewogICAgICAgIFNULnVwZGF0ZShwLmZpcnN0LCBwLnNlY29uZCwgMSk7CiAgICB9CgogICAgbWFwPGludCwgVHJlYXBfdG9fRmluZD4gUE9TSVRJT05TOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICBQT1NJVElPTlNbYVtpXV0uQWRkKGkpOwogICAgfQogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICBpZiAoUE9TSVRJT05TW2FbaV1dLkZpbmQoLTEpID09IGZhbHNlKSB7CiAgICAgICAgICAgIFBPU0lUSU9OU1thW2ldXS5BZGQoLTEpOwogICAgICAgIH0KICAgICAgICBpZiAoUE9TSVRJT05TW2FbaV1dLkZpbmQobikgPT0gZmFsc2UpIHsKICAgICAgICAgICAgUE9TSVRJT05TW2FbaV1dLkFkZChuKTsKICAgICAgICB9CiAgICB9CgogICAgaW50IHE7IGNpbiA+PiBxOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBxOyBpKyspIHsKICAgICAgICBzdHJpbmcgVHlwZTsgY2luID4+IFR5cGU7CgogICAgICAgIGlmIChUeXBlID09ICIhIikgewogICAgICAgICAgICBpbnQgcG9zLCB2YWw7IGNpbiA+PiBwb3MgPj4gdmFsOwoKICAgICAgICAgICAgLS1wb3M7CgogICAgICAgICAgICBpZiAoYVtwb3NdID09IHZhbCkgewogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChmdXR1cmVbcG9zXSAhPSBuKSB7CiAgICAgICAgICAgICAgICBMQVNULnVwZGF0ZShmdXR1cmVbcG9zXSwgcG9zLCAxJzAwMCcwMDAgLSBsYXN0W3Bvc10pOwogICAgICAgICAgICAgICAgU1QudXBkYXRlKGxhc3RbZnV0dXJlW3Bvc11dLCBmdXR1cmVbZnV0dXJlW3Bvc11dLCAtMSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKDEnMDAwJzAwMCAtIGxhc3RbcG9zXSAhPSAtMSkgewogICAgICAgICAgICAgICAgRlVUVVJFLnVwZGF0ZSgxJzAwMCcwMDAgLSBsYXN0W3Bvc10sIHBvcywgZnV0dXJlW3Bvc10pOwogICAgICAgICAgICAgICAgU1QudXBkYXRlKGxhc3RbMScwMDAnMDAwIC0gbGFzdFtwb3NdXSwgZnV0dXJlWzEnMDAwJzAwMCAtIGxhc3RbcG9zXV0sIC0xKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgaWYgKGZ1dHVyZVtwb3NdICE9IG4pIHsKICAgICAgICAgICAgICAgIGxhc3RbZnV0dXJlW3Bvc11dID0gbGFzdFtwb3NdOwogICAgICAgICAgICAgICAgU1QudXBkYXRlKGxhc3RbZnV0dXJlW3Bvc11dLCBmdXR1cmVbZnV0dXJlW3Bvc11dLCAxKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoMScwMDAnMDAwIC0gbGFzdFtwb3NdICE9IC0xKSB7CiAgICAgICAgICAgICAgICBmdXR1cmVbMScwMDAnMDAwIC0gbGFzdFtwb3NdXSA9IGZ1dHVyZVtwb3NdOwogICAgICAgICAgICAgICAgU1QudXBkYXRlKGxhc3RbMScwMDAnMDAwIC0gbGFzdFtwb3NdXSwgZnV0dXJlWzEnMDAwJzAwMCAtIGxhc3RbcG9zXV0sIDEpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBTVC51cGRhdGUobGFzdFtwb3NdLCBmdXR1cmVbcG9zXSwgLTEpOwoKICAgICAgICAgICAgUE9TSVRJT05TW2FbcG9zXV0uRGVsKHBvcyk7CiAgICAgICAgICAgIFBPU0lUSU9OU1t2YWxdLkFkZChwb3MpOwoKICAgICAgICAgICAgaWYgKFBPU0lUSU9OU1t2YWxdLkZpbmQoLTEpID09IGZhbHNlKSB7CiAgICAgICAgICAgICAgICBQT1NJVElPTlNbdmFsXS5BZGQoLTEpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChQT1NJVElPTlNbdmFsXS5GaW5kKG4pID09IGZhbHNlKSB7CiAgICAgICAgICAgICAgICBQT1NJVElPTlNbdmFsXS5BZGQobik7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGludCBMYXN0X2Zvcl92YWwgPSBQT1NJVElPTlNbdmFsXS5GaW5kX2xsKHBvcyk7CiAgICAgICAgICAgIGludCBGdXR1cmVfZm9yX3ZhbCA9IFBPU0lUSU9OU1t2YWxdLkZpbmRfcnIocG9zKTsKCiAgICAgICAgICAgIExBU1QudXBkYXRlKHBvcywgMScwMDAnMDAwIC0gbGFzdFtwb3NdLCBMYXN0X2Zvcl92YWwpOwogICAgICAgICAgICBGVVRVUkUudXBkYXRlKHBvcywgZnV0dXJlW3Bvc10sIEZ1dHVyZV9mb3JfdmFsKTsKCiAgICAgICAgICAgIGxhc3RbcG9zXSA9IDEnMDAwJzAwMCAtIFBPU0lUSU9OU1t2YWxdLkZpbmRfbGwocG9zKTsKICAgICAgICAgICAgZnV0dXJlW3Bvc10gPSBQT1NJVElPTlNbdmFsXS5GaW5kX3JyKHBvcyk7CgogICAgICAgICAgICBhW3Bvc10gPSB2YWw7CgogICAgICAgICAgICBTVC51cGRhdGUobGFzdFtwb3NdLCBmdXR1cmVbcG9zXSwgMSk7CgogICAgICAgICAgICBpZiAoRnV0dXJlX2Zvcl92YWwgIT0gbikgewogICAgICAgICAgICAgICAgTEFTVC51cGRhdGUoRnV0dXJlX2Zvcl92YWwsIExhc3RfZm9yX3ZhbCwgcG9zKTsKICAgICAgICAgICAgICAgIFNULnVwZGF0ZShsYXN0W0Z1dHVyZV9mb3JfdmFsXSwgZnV0dXJlW0Z1dHVyZV9mb3JfdmFsXSwgLTEpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChMYXN0X2Zvcl92YWwgIT0gLTEpIHsKICAgICAgICAgICAgICAgIEZVVFVSRS51cGRhdGUoTGFzdF9mb3JfdmFsLCBGdXR1cmVfZm9yX3ZhbCwgcG9zKTsKICAgICAgICAgICAgICAgIFNULnVwZGF0ZShsYXN0W0xhc3RfZm9yX3ZhbF0sIGZ1dHVyZVtMYXN0X2Zvcl92YWxdLCAtMSk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChGdXR1cmVfZm9yX3ZhbCAhPSBuKSB7CiAgICAgICAgICAgICAgICBsYXN0W0Z1dHVyZV9mb3JfdmFsXSA9IDEnMDAwJzAwMCAtIHBvczsKICAgICAgICAgICAgICAgIFNULnVwZGF0ZShsYXN0W0Z1dHVyZV9mb3JfdmFsXSwgZnV0dXJlW0Z1dHVyZV9mb3JfdmFsXSwgMSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKExhc3RfZm9yX3ZhbCAhPSAtMSkgewogICAgICAgICAgICAgICAgZnV0dXJlW0xhc3RfZm9yX3ZhbF0gPSBwb3M7CiAgICAgICAgICAgICAgICBTVC51cGRhdGUobGFzdFtMYXN0X2Zvcl92YWxdLCBmdXR1cmVbTGFzdF9mb3JfdmFsXSwgMSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIGludCBsLCByOyBjaW4gPj4gbCA+PiByOwoKICAgICAgICAgICAgLS1sOwogICAgICAgICAgICAtLXI7CgogICAgICAgICAgICBpbnQgbWluX1ggPSAxJzAwMCcwMDAgLSBsOwogICAgICAgICAgICBpbnQgbWluX1kgPSByOwoKICAgICAgICAgICAgY291dCA8PCBTVC5xdWVyeShtaW5fWCArIDEsIG1pbl9ZICsgMSwgaW5mLCBpbmYpIC0gTEFTVC5xdWVyeV9MKHIgKyAxLCBuIC0gMSwgbCAtIDEpIC0gRlVUVVJFLnF1ZXJ5X1IoMCwgbCAtIDEsIHIgKyAxKSA8PCBlbmRsOwogICAgICAgIH0KICAgIH0KfQoKc2lnbmVkIG1haW4oKSB7CiAgICBpb3NfYmFzZTo6c3luY193aXRoX3N0ZGlvKGZhbHNlKTsKICAgIGNpbi50aWUoMCk7CiAgICBjb3V0LnRpZSgwKTsKCiAgICAvKgogICAgICAgICAgICAgICAgICAgICAgX19fX19fX19fX19fX19fXwogICAgICAgICAgICAgICAgICAgICAvIEp1c3Qgc29sdmVkIGl0IFwKICAgICAgICAgICAgICAgICAgICAgfCAgIGluIG15IG1pbmQgICB8CiAgICAgICAgICAgICAgICAgICAgIFxfX19fX19fX19fX19fX19fLwogICAgICAgICAgICAgICAgICAgIC8KICAgICAgICAgICAgICAgICAgIC8K44CA44CA44CA44CA44CA77yP77ye44CAIOODlSAgICAgICAgIF9fX19fX19fX19fCuOAgOOAgOOAgOOAgOOAgHwg44CAX+OAgCBffCAgICAgICB8ICAgICAgICAgIHwK44CAIOOAgOOAgOOAgO+8j2Djg58gX3gg5b2hICAgICAgIHwgICBXQSAyICAgfArjgIDjgIAg44CAIC/jgIDjgIDjgIAg44CAIHwgICAgICAgfF9fX19fX19fX198CuOAgOOAgOOAgCAv44CAIOODveOAgOOAgCDvvokgICAgICAgIC8gICAgICAgICAgLwrjgIDvvI/vv6N844CA44CAIHzjgIB844CAfCAgICAgICAvX19fX19fX19fIC8K44CAfCAo77+j44O977y/X+ODvV8pXykK44CA77y85LqM44GkCgogICAgKi8KCiAgICAvKgogICAgZnJlb3BlbigiaW5wdXQudHh0IiwgInIiLCBzdGRpbik7CiAgICBmcmVvcGVuKCJvdXRwdXQudHh0IiwgInciLCBzdGRvdXQpOwogICAgKi8KCiAgICAvLyBhdXRvIHN0YXJ0ID0gY2hyb25vOjpoaWdoX3Jlc29sdXRpb25fY2xvY2s6Om5vdygpOwoKICAgIGludCBtdWx0aXRlc3QgPSBmYWxzZTsKICAgIGlmIChtdWx0aXRlc3QgPT0gdHJ1ZSkgewogICAgICAgIGludCBjdHQ7IGNpbiA+PiBjdHQ7CgogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgY3R0OyBpKyspIHsKICAgICAgICAgICAgU29sdmUoKTsKICAgICAgICB9CiAgICB9CiAgICBlbHNlIHsKICAgICAgICBTb2x2ZSgpOwogICAgfQoKICAgIC8vIGF1dG8gZW5kID0gY2hyb25vOjpoaWdoX3Jlc29sdXRpb25fY2xvY2s6Om5vdygpOwoKICAgIC8qCiAgICBjb3V0IDw8ICJUaW1lIHRha2VuOiAiCiAgICAgICAgIDw8IGNocm9ubzo6ZHVyYXRpb25fY2FzdDxjaHJvbm86Om1pbGxpc2Vjb25kcz4oZW5kIC0gc3RhcnQpLmNvdW50KCkKICAgICAgICAgPDwgIiBtaWxsaXNlY29uZHMiIDw8IGVuZGw7CiAgICAqLwoKICAgIHJldHVybiAwOwp9