#include <stdio.h>
#include <algorithm>
#include <assert.h>
#include <set>
#include <map>
#include <complex>
#include <iostream>
#include <time.h>
#include <stack>
#include <stdlib.h>
#include <memory.h>
#include <bitset>
#include <math.h>
#include <string>
#include <string.h>
#include <queue>
#include <vector>
using namespace std;
const int MaxN = 1e5 + 10;
const int MOD = 1e9 + 7;
const int INF = 1e9;
typedef long double PrecisionType;
typedef pair < PrecisionType, PrecisionType > PointType;
const PrecisionType EPS = 1e-10;
struct Node {
PointType x;
int y, sz;
PrecisionType sq;
PointType lmost, rmost;
Node *l, *r;
Node() {
}
Node(PointType _x) : sq(0.0), x(_x), lmost(_x), rmost(_x), sz(1), y(rand() * RAND_MAX + rand()), l(NULL), r(NULL) {
}
friend int getSize(Node *t) {
return t != NULL ? t->sz : 0;
}
friend PrecisionType getSquare(Node *t) {
return t ? t->sq : 0;
}
friend void update(Node *t) {
if (t != NULL) {
t->sz = 1;
t->lmost = t->rmost = t->x;
t->sq = 0;
if (t->r != NULL) {
t->sq += t->r->sq;
t->sq += (PrecisionType)(+t->r->lmost.first - t->x.first) * (PrecisionType)(t->r->lmost.second + t->x.second);
t->rmost = t->r->rmost;
t->sz += t->r->sz;
}
if (t->l != NULL) {
t->sq += t->l->sq;
t->sq += (PrecisionType)(-t->l->rmost.first + t->x.first) * (PrecisionType)(t->l->rmost.second + t->x.second);
t->lmost = t->l->lmost;
t->sz += t->l->sz;
}
}
}
friend void split(Node *t, Node *&l, Node *&r, PointType x) {
if (!t) {
r = l = NULL;
return;
}
if (t->x.first <= x.first) {
split(t->r, t->r, r, x);
l = t;
update(l);
return;
}
split(t->l, l, t->l, x);
r = t;
update(r);
}
friend Node* merge(Node *l, Node *r) {
if (!l || !r) {
return l ? l : r;
}
if (l->y > r->y) {
l->r = merge(l->r, r);
update(l);
return l;
}
r->l = merge(l, r->l);
update(r);
return r;
}
};
PrecisionType dist(PointType a, PointType b) {
return hypotl(a.first - b.first + .0, a.second - b.second + .0);
}
PrecisionType dist2(PointType a, PointType b) {
return (b.first - a.first) * (b.first - a.first) + (b.second - a.second) * (b.second - a.second);
}
PrecisionType cw(PointType a, PointType b, PointType c) {
return (a.first - b.first) * (c.second - b.second) - (a.second - b.second) * (c.first - b.first);
}
bool upcw(PointType a, PointType b, PointType c) {
return cw(a, b, c) > 0;
}
bool dwcw(PointType a, PointType b, PointType c) {
return cw(a, b, c) < 0;
}
PrecisionType getY(PointType a, PointType b, PointType c) {
return (c.first - a.first) / (b.first - a.first) * (b.second - a.second) + a.second;
}
Node *leftFound(Node *root, PointType point, bool (*myCw)(PointType, PointType, PointType)) {
if (root->l != NULL) {
if (!myCw(root->l->rmost, root->x, point)) {
return leftFound(root->l, point, myCw);
}
}
if (root->r != NULL) {
if (myCw(root->x, root->r->lmost, point)) {
return leftFound(root->r, point, myCw);
}
}
return root;
}
Node *rightFound(Node *root, PointType point, bool (*myCw)(PointType, PointType, PointType)) {
if (root->r != NULL) {
if (!myCw(point, root->x, root->r->lmost)) {
return rightFound(root->r, point, myCw);
}
}
if (root->l != NULL) {
if (myCw(point, root->l->rmost, root->x)) {
return rightFound(root->l, point, myCw);
}
}
return root;
}
bool exist(Node *root, PointType p) {
if (!root) {
return false;
}
if (root->x.first == p.first) {
return true;
}
if (root->x.first < p.first) {
return exist(root->r, p);
}
return exist(root->l, p);
}
bool addPoint(vector < pair < PointType, Node* > > &roll, Node *&convexHull, PointType point, bool isUp, bool (*myCw)(PointType, PointType, PointType)) {
if (exist(convexHull, point)) {
return false;
}
if (!convexHull) {
convexHull = new Node(point);
roll.push_back(make_pair(point, (Node*)NULL));
return true;
}
if (convexHull->lmost <= point && point <= convexHull->rmost) {
Node *leftConvexHull, *rightConvexHull;
split(convexHull, leftConvexHull, rightConvexHull, point);
PointType l = leftConvexHull->rmost;
PointType r = rightConvexHull->lmost;
PrecisionType y = getY(l, r, point);
if (isUp == true && point.second > y || isUp == false && point.second < y) {
Node *whereL = leftFound(leftConvexHull, point, myCw);
Node *whereR = rightFound(rightConvexHull, point, myCw);
Node *a, *b;
split(leftConvexHull, leftConvexHull, a, make_pair(whereL->x.first, whereL->x.second));
split(rightConvexHull, b, rightConvexHull, make_pair(whereR->x.first - 1e-10, whereR->x.second));
convexHull = merge(leftConvexHull, merge(new Node(point), rightConvexHull));
roll.push_back(make_pair(point, merge(a, b)));
return true;
}
convexHull = merge(leftConvexHull, rightConvexHull);
return false;
}
if (point <= convexHull->lmost) {
Node *whereR = rightFound(convexHull, point, myCw);
Node *temp;
split(convexHull, temp, convexHull, make_pair(whereR->x.first - 1e-10, whereR->x.second));
roll.push_back(make_pair(point, temp));
convexHull = merge(new Node(point), convexHull);
} else {
Node *whereL = leftFound(convexHull, point, myCw);
Node *temp;
split(convexHull, convexHull, temp, make_pair(whereL->x.first, whereL->x.second));
roll.push_back(make_pair(point, temp));
convexHull = merge(convexHull, new Node(point));
}
return true;
}
PointType rotate(PointType point, PrecisionType ang) {
return PointType(point.first * cosl(ang) + point.second * sinl(ang), -point.first * sinl(ang) + point.second * cosl(ang));
}
void makeChange(Node *&upConvexHull,
Node *&downConvexHull,
vector < pair < PointType, Node* > > &upChanges,
vector < pair < PointType, Node* > > &downChanges,
PointType point) {
addPoint(upChanges, upConvexHull, point, true, upcw);
addPoint(downChanges, downConvexHull, point, false, dwcw);
}
void rollback(Node *&convexHull, vector < pair < PointType, Node* > > &roll, int oldSize) {
while (roll.size() > oldSize) {
PointType cur = roll.back().first;
Node *tree = roll.back().second;
Node *a, *b;
split(convexHull, convexHull, a, make_pair(cur.first - 1e-10, cur.second));
split(a, a, b, make_pair(cur.first + 1e-10, cur.second));
convexHull = merge(convexHull, merge(tree, b));
roll.pop_back();
}
}
void solve(Node *&upConvexHull,
Node *&downConvexHull,
vector < pair < PointType, Node* > > &upChanges,
vector < pair < PointType, Node* > > &downChanges,
vector < pair < char, PointType > > &queries,
vector < int > &wadd,
vector < int > &paired,
vector < PrecisionType > &answers,
int lbound, int rbound) {
int middle = (lbound + rbound) / 2;
int upch = upChanges.size(), dwch = downChanges.size();
vector < int > nadd;
for (int i = 0; i < (int)wadd.size(); ++i) {
int l = wadd[i], r = paired[l];
if (r < lbound || l > rbound) {
continue;
}
if (l <= lbound && r > rbound) {
makeChange(upConvexHull, downConvexHull, upChanges, downChanges, queries[l].second);
continue;
}
nadd.push_back(wadd[i]);
}
if (lbound != rbound) {
solve(upConvexHull, downConvexHull, upChanges, downChanges, queries, nadd, paired, answers, lbound, middle);
solve(upConvexHull, downConvexHull, upChanges, downChanges, queries, nadd, paired, answers, middle + 1, rbound);
} else {
answers[lbound] = abs((getSquare(upConvexHull) - getSquare(downConvexHull)) / 2.0);
}
rollback(upConvexHull, upChanges, upch);
rollback(downConvexHull, downChanges, dwch);
}
vector < PrecisionType > solveSmart(vector < pair < char, PointType > > queries) {
int q = (int)queries.size();
map < PointType, vector < int > > f;
vector < int > paired(q);
for (int i = 0; i < q; ++i) {
char type = queries[i].first;
PointType point = queries[i].second;
if (type == '+') {
f[point].push_back(i);
} else {
int where = f[point].back();
f[point].pop_back();
paired[where] = i;
paired[i] = where;
}
}
vector < int > wadd;
for (int i = 0; i < q; ++i) {
char type = queries[i].first;
PointType point = queries[i].second;
if (type == '+') {
wadd.push_back(i);
}
if (type == '-' || f[point].empty()) {
continue;
}
for (int j = 0; j < (int)f[point].size(); ++j) {
int where = f[point][j];
paired[where] = q;
}
f[point].clear();
}
vector < PrecisionType > ans(q);
Node *upConvexHull = NULL, *downConvexHull = NULL;
vector < pair < PointType, Node* > > upChanges, downChanges;
solve(upConvexHull, downConvexHull, upChanges, downChanges, queries, wadd, paired, ans, 0, q - 1);
return ans;
}
namespace stupid {
vector < PointType > convexHull(vector < PointType > points) {
sort(points.begin(), points.end());
if (points.size() < 3) {
return points;
}
vector < PointType > up, down;
up.push_back(points[0]);
down.push_back(points[0]);
for (int i = 1; i < (int)points.size(); ++i) {
if (i == (int)points.size() - 1 || cw(points[0], points[i], points.back()) > 0) {
while (up.size() >= 2 && cw(up[up.size() - 2], up[up.size() - 1], points[i]) <= 0) {
up.pop_back();
}
up.push_back(points[i]);
}
if (i == (int)points.size() - 1 || cw(points[0], points[i], points.back()) < 0) {
while (down.size() >= 2 && cw(down[down.size() - 2], down[down.size() - 1], points[i]) >= 0) {
down.pop_back();
}
down.push_back(points[i]);
}
}
vector < PointType > res;
for (int i = 0; i < (int)up.size(); ++i) {
res.push_back(up[i]);
}
for (int i = (int)down.size() - 2; i > 0; --i) {
res.push_back(down[i]);
}
return res;
}
void solve(vector < pair < char, PointType > > queries) {
multiset < PointType > points;
for (int i = 0; i < (int)queries.size(); ++i) {
PointType point = queries[i].second;
if (queries[i].first == '+') {
points.insert(point);
} else {
if (points.find(point) != points.end()) {
points.erase(points.find(point));
}
}
PrecisionType ans = 0;
if (points.size() >= 3) {
vector < PointType > v(points.begin(), points.end());
v = convexHull(v);
if (v.size() >= 3) {
for (int i = 0; i < (int)v.size(); ++i) {
ans += (PrecisionType)(v[i].first - v[(i + 1) % v.size()].first) * (v[i].second + v[(i + 1) % v.size()].second);
}
}
}
long long res = (ans >= 0 ? (long long)(ans + 0.5) : (long long)(ans - 0.5));
printf("%lld.%lld\n", abs(res) / 2, abs(res) % 2 * 5);
}
}
};
int main() {
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
int t;
scanf("%d", &t);
while (t --> 0) {
int q;
scanf("%d", &q);
vector < pair < char, PointType > > queries(q);
for (int i = 0; i < q; ++i) {
int x, y;
scanf("\n%c%d%d", &queries[i].first, &x, &y);
queries[i].second.first = x;
queries[i].second.second = y;
}
// stupid::solve(queries);
// exit(0);
for (int i = 0; i < q; ++i) {
queries[i].second = rotate(queries[i].second, +13.0);
}
vector < PrecisionType > ans = solveSmart(queries);
for (int i = 0; i < (int)ans.size(); ++i) {
printf("%.1lf\n", (double)ans[i]);
}
}
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxhbGdvcml0aG0+CiNpbmNsdWRlIDxhc3NlcnQuaD4KI2luY2x1ZGUgPHNldD4KI2luY2x1ZGUgPG1hcD4KI2luY2x1ZGUgPGNvbXBsZXg+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPHRpbWUuaD4KI2luY2x1ZGUgPHN0YWNrPgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlIDxtZW1vcnkuaD4KI2luY2x1ZGUgPGJpdHNldD4KI2luY2x1ZGUgPG1hdGguaD4KI2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8cXVldWU+CiNpbmNsdWRlIDx2ZWN0b3I+CiAKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKIApjb25zdCBpbnQgTWF4TiA9IDFlNSArIDEwOwpjb25zdCBpbnQgTU9EID0gMWU5ICsgNzsKY29uc3QgaW50IElORiA9IDFlOTsKIAp0eXBlZGVmIGxvbmcgZG91YmxlIFByZWNpc2lvblR5cGU7CnR5cGVkZWYgcGFpciA8IFByZWNpc2lvblR5cGUsIFByZWNpc2lvblR5cGUgPiBQb2ludFR5cGU7CiAKY29uc3QgUHJlY2lzaW9uVHlwZSBFUFMgPSAxZS0xMDsKIApzdHJ1Y3QgTm9kZSB7CiAgUG9pbnRUeXBlIHg7CiAgaW50IHksIHN6OwogIFByZWNpc2lvblR5cGUgc3E7CiAgUG9pbnRUeXBlIGxtb3N0LCBybW9zdDsKICBOb2RlICpsLCAqcjsKICBOb2RlKCkgewogIH0KICBOb2RlKFBvaW50VHlwZSBfeCkgOiBzcSgwLjApLCB4KF94KSwgbG1vc3QoX3gpLCBybW9zdChfeCksIHN6KDEpLCB5KHJhbmQoKSAqIFJBTkRfTUFYICsgcmFuZCgpKSwgbChOVUxMKSwgcihOVUxMKSB7CiAgfQogIGZyaWVuZCBpbnQgZ2V0U2l6ZShOb2RlICp0KSB7CiAgICByZXR1cm4gdCAhPSBOVUxMID8gdC0+c3ogOiAwOwogIH0KICBmcmllbmQgUHJlY2lzaW9uVHlwZSBnZXRTcXVhcmUoTm9kZSAqdCkgewogICAgcmV0dXJuIHQgPyB0LT5zcSA6IDA7CiAgfQogIGZyaWVuZCB2b2lkIHVwZGF0ZShOb2RlICp0KSB7CiAgICBpZiAodCAhPSBOVUxMKSB7CiAgICAgIHQtPnN6ID0gMTsKICAgICAgdC0+bG1vc3QgPSB0LT5ybW9zdCA9IHQtPng7CiAgICAgIHQtPnNxID0gMDsKICAgICAgaWYgKHQtPnIgIT0gTlVMTCkgewogICAgICAgIHQtPnNxICs9IHQtPnItPnNxOwogICAgICAgIHQtPnNxICs9IChQcmVjaXNpb25UeXBlKSgrdC0+ci0+bG1vc3QuZmlyc3QgLSB0LT54LmZpcnN0KSAqIChQcmVjaXNpb25UeXBlKSh0LT5yLT5sbW9zdC5zZWNvbmQgKyB0LT54LnNlY29uZCk7CiAgICAgICAgdC0+cm1vc3QgPSB0LT5yLT5ybW9zdDsKICAgICAgICB0LT5zeiArPSB0LT5yLT5zejsKICAgICAgfQogICAgICBpZiAodC0+bCAhPSBOVUxMKSB7CiAgICAgICAgdC0+c3EgKz0gdC0+bC0+c3E7CiAgICAgICAgdC0+c3EgKz0gKFByZWNpc2lvblR5cGUpKC10LT5sLT5ybW9zdC5maXJzdCArIHQtPnguZmlyc3QpICogKFByZWNpc2lvblR5cGUpKHQtPmwtPnJtb3N0LnNlY29uZCArIHQtPnguc2Vjb25kKTsKICAgICAgICB0LT5sbW9zdCA9IHQtPmwtPmxtb3N0OwogICAgICAgIHQtPnN6ICs9IHQtPmwtPnN6OwogICAgICB9CiAgICB9CiAgfQogIGZyaWVuZCB2b2lkIHNwbGl0KE5vZGUgKnQsIE5vZGUgKiZsLCBOb2RlIComciwgUG9pbnRUeXBlIHgpIHsKICAgIGlmICghdCkgewogICAgICByID0gbCA9IE5VTEw7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICh0LT54LmZpcnN0IDw9IHguZmlyc3QpIHsKICAgICAgc3BsaXQodC0+ciwgdC0+ciwgciwgeCk7CiAgICAgIGwgPSB0OwogICAgICB1cGRhdGUobCk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHNwbGl0KHQtPmwsIGwsIHQtPmwsIHgpOwogICAgciA9IHQ7CiAgICB1cGRhdGUocik7CiAgfQogIGZyaWVuZCBOb2RlKiBtZXJnZShOb2RlICpsLCBOb2RlICpyKSB7CiAgICBpZiAoIWwgfHwgIXIpIHsKICAgICAgcmV0dXJuIGwgPyBsIDogcjsKICAgIH0KICAgIGlmIChsLT55ID4gci0+eSkgewogICAgICBsLT5yID0gbWVyZ2UobC0+ciwgcik7CiAgICAgIHVwZGF0ZShsKTsKICAgICAgcmV0dXJuIGw7CiAgICB9CiAgICByLT5sID0gbWVyZ2UobCwgci0+bCk7CiAgICB1cGRhdGUocik7CiAgICByZXR1cm4gcjsKICB9Cn07CiAKUHJlY2lzaW9uVHlwZSBkaXN0KFBvaW50VHlwZSBhLCBQb2ludFR5cGUgYikgewogIHJldHVybiBoeXBvdGwoYS5maXJzdCAtIGIuZmlyc3QgKyAuMCwgYS5zZWNvbmQgLSBiLnNlY29uZCArIC4wKTsKfQogClByZWNpc2lvblR5cGUgZGlzdDIoUG9pbnRUeXBlIGEsIFBvaW50VHlwZSBiKSB7CiAgcmV0dXJuIChiLmZpcnN0IC0gYS5maXJzdCkgKiAoYi5maXJzdCAtIGEuZmlyc3QpICsgKGIuc2Vjb25kIC0gYS5zZWNvbmQpICogKGIuc2Vjb25kIC0gYS5zZWNvbmQpOwp9CiAKUHJlY2lzaW9uVHlwZSBjdyhQb2ludFR5cGUgYSwgUG9pbnRUeXBlIGIsIFBvaW50VHlwZSBjKSB7CiAgcmV0dXJuIChhLmZpcnN0IC0gYi5maXJzdCkgKiAoYy5zZWNvbmQgLSBiLnNlY29uZCkgLSAoYS5zZWNvbmQgLSBiLnNlY29uZCkgKiAoYy5maXJzdCAtIGIuZmlyc3QpOwp9CiAKYm9vbCB1cGN3KFBvaW50VHlwZSBhLCBQb2ludFR5cGUgYiwgUG9pbnRUeXBlIGMpIHsKICByZXR1cm4gY3coYSwgYiwgYykgPiAwOwp9CiAKYm9vbCBkd2N3KFBvaW50VHlwZSBhLCBQb2ludFR5cGUgYiwgUG9pbnRUeXBlIGMpIHsKICByZXR1cm4gY3coYSwgYiwgYykgPCAwOwp9CiAKUHJlY2lzaW9uVHlwZSBnZXRZKFBvaW50VHlwZSBhLCBQb2ludFR5cGUgYiwgUG9pbnRUeXBlIGMpIHsKICByZXR1cm4gKGMuZmlyc3QgLSBhLmZpcnN0KSAvIChiLmZpcnN0IC0gYS5maXJzdCkgKiAoYi5zZWNvbmQgLSBhLnNlY29uZCkgKyBhLnNlY29uZDsKfQogCk5vZGUgKmxlZnRGb3VuZChOb2RlICpyb290LCBQb2ludFR5cGUgcG9pbnQsIGJvb2wgKCpteUN3KShQb2ludFR5cGUsIFBvaW50VHlwZSwgUG9pbnRUeXBlKSkgewogIGlmIChyb290LT5sICE9IE5VTEwpIHsKICAgIGlmICghbXlDdyhyb290LT5sLT5ybW9zdCwgcm9vdC0+eCwgcG9pbnQpKSB7CiAgICAgIHJldHVybiBsZWZ0Rm91bmQocm9vdC0+bCwgcG9pbnQsIG15Q3cpOwogICAgfQogIH0KICBpZiAocm9vdC0+ciAhPSBOVUxMKSB7CiAgICBpZiAobXlDdyhyb290LT54LCByb290LT5yLT5sbW9zdCwgcG9pbnQpKSB7CiAgICAgIHJldHVybiBsZWZ0Rm91bmQocm9vdC0+ciwgcG9pbnQsIG15Q3cpOwogICAgfQogIH0KICByZXR1cm4gcm9vdDsKfQogCk5vZGUgKnJpZ2h0Rm91bmQoTm9kZSAqcm9vdCwgUG9pbnRUeXBlIHBvaW50LCBib29sICgqbXlDdykoUG9pbnRUeXBlLCBQb2ludFR5cGUsIFBvaW50VHlwZSkpIHsKICBpZiAocm9vdC0+ciAhPSBOVUxMKSB7CiAgICBpZiAoIW15Q3cocG9pbnQsIHJvb3QtPngsIHJvb3QtPnItPmxtb3N0KSkgewogICAgICByZXR1cm4gcmlnaHRGb3VuZChyb290LT5yLCBwb2ludCwgbXlDdyk7CiAgICB9CiAgfQogIGlmIChyb290LT5sICE9IE5VTEwpIHsKICAgIGlmIChteUN3KHBvaW50LCByb290LT5sLT5ybW9zdCwgcm9vdC0+eCkpIHsKICAgICAgcmV0dXJuIHJpZ2h0Rm91bmQocm9vdC0+bCwgcG9pbnQsIG15Q3cpOwogICAgfQogIH0KICByZXR1cm4gcm9vdDsKfQogCmJvb2wgZXhpc3QoTm9kZSAqcm9vdCwgUG9pbnRUeXBlIHApIHsKICBpZiAoIXJvb3QpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgaWYgKHJvb3QtPnguZmlyc3QgPT0gcC5maXJzdCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIGlmIChyb290LT54LmZpcnN0IDwgcC5maXJzdCkgewogICAgcmV0dXJuIGV4aXN0KHJvb3QtPnIsIHApOwogIH0KICByZXR1cm4gZXhpc3Qocm9vdC0+bCwgcCk7Cn0KIApib29sIGFkZFBvaW50KHZlY3RvciA8IHBhaXIgPCBQb2ludFR5cGUsIE5vZGUqID4gPiAmcm9sbCwgTm9kZSAqJmNvbnZleEh1bGwsIFBvaW50VHlwZSBwb2ludCwgYm9vbCBpc1VwLCBib29sICgqbXlDdykoUG9pbnRUeXBlLCBQb2ludFR5cGUsIFBvaW50VHlwZSkpIHsKICBpZiAoZXhpc3QoY29udmV4SHVsbCwgcG9pbnQpKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGlmICghY29udmV4SHVsbCkgewogICAgY29udmV4SHVsbCA9IG5ldyBOb2RlKHBvaW50KTsKICAgIHJvbGwucHVzaF9iYWNrKG1ha2VfcGFpcihwb2ludCwgKE5vZGUqKU5VTEwpKTsKICAgIHJldHVybiB0cnVlOwogIH0KICBpZiAoY29udmV4SHVsbC0+bG1vc3QgPD0gcG9pbnQgJiYgcG9pbnQgPD0gY29udmV4SHVsbC0+cm1vc3QpIHsKICAgIE5vZGUgKmxlZnRDb252ZXhIdWxsLCAqcmlnaHRDb252ZXhIdWxsOwogICAgc3BsaXQoY29udmV4SHVsbCwgbGVmdENvbnZleEh1bGwsIHJpZ2h0Q29udmV4SHVsbCwgcG9pbnQpOwogICAgUG9pbnRUeXBlIGwgPSBsZWZ0Q29udmV4SHVsbC0+cm1vc3Q7CiAgICBQb2ludFR5cGUgciA9IHJpZ2h0Q29udmV4SHVsbC0+bG1vc3Q7CiAgICBQcmVjaXNpb25UeXBlIHkgPSBnZXRZKGwsIHIsIHBvaW50KTsKICAgIGlmIChpc1VwID09IHRydWUgJiYgcG9pbnQuc2Vjb25kID4geSB8fCBpc1VwID09IGZhbHNlICYmIHBvaW50LnNlY29uZCA8IHkpIHsKICAgICAgTm9kZSAqd2hlcmVMID0gbGVmdEZvdW5kKGxlZnRDb252ZXhIdWxsLCBwb2ludCwgbXlDdyk7CiAgICAgIE5vZGUgKndoZXJlUiA9IHJpZ2h0Rm91bmQocmlnaHRDb252ZXhIdWxsLCBwb2ludCwgbXlDdyk7CiAgICAgIE5vZGUgKmEsICpiOwogICAgICBzcGxpdChsZWZ0Q29udmV4SHVsbCwgbGVmdENvbnZleEh1bGwsIGEsICBtYWtlX3BhaXIod2hlcmVMLT54LmZpcnN0LCB3aGVyZUwtPnguc2Vjb25kKSk7CiAgICAgIHNwbGl0KHJpZ2h0Q29udmV4SHVsbCwgYiwgcmlnaHRDb252ZXhIdWxsLCBtYWtlX3BhaXIod2hlcmVSLT54LmZpcnN0IC0gMWUtMTAsIHdoZXJlUi0+eC5zZWNvbmQpKTsKICAgICAgY29udmV4SHVsbCA9IG1lcmdlKGxlZnRDb252ZXhIdWxsLCBtZXJnZShuZXcgTm9kZShwb2ludCksIHJpZ2h0Q29udmV4SHVsbCkpOwogICAgICByb2xsLnB1c2hfYmFjayhtYWtlX3BhaXIocG9pbnQsIG1lcmdlKGEsIGIpKSk7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgY29udmV4SHVsbCA9IG1lcmdlKGxlZnRDb252ZXhIdWxsLCByaWdodENvbnZleEh1bGwpOwogICAgcmV0dXJuIGZhbHNlOwogIH0KICBpZiAocG9pbnQgPD0gY29udmV4SHVsbC0+bG1vc3QpIHsKICAgIE5vZGUgKndoZXJlUiA9IHJpZ2h0Rm91bmQoY29udmV4SHVsbCwgcG9pbnQsIG15Q3cpOwogICAgTm9kZSAqdGVtcDsKICAgIHNwbGl0KGNvbnZleEh1bGwsIHRlbXAsIGNvbnZleEh1bGwsIG1ha2VfcGFpcih3aGVyZVItPnguZmlyc3QgLSAxZS0xMCwgd2hlcmVSLT54LnNlY29uZCkpOwogICAgcm9sbC5wdXNoX2JhY2sobWFrZV9wYWlyKHBvaW50LCB0ZW1wKSk7CiAgICBjb252ZXhIdWxsID0gbWVyZ2UobmV3IE5vZGUocG9pbnQpLCBjb252ZXhIdWxsKTsKICB9IGVsc2UgewogICAgTm9kZSAqd2hlcmVMID0gbGVmdEZvdW5kKGNvbnZleEh1bGwsIHBvaW50LCBteUN3KTsKICAgIE5vZGUgKnRlbXA7CiAgICBzcGxpdChjb252ZXhIdWxsLCBjb252ZXhIdWxsLCB0ZW1wLCBtYWtlX3BhaXIod2hlcmVMLT54LmZpcnN0LCB3aGVyZUwtPnguc2Vjb25kKSk7CiAgICByb2xsLnB1c2hfYmFjayhtYWtlX3BhaXIocG9pbnQsIHRlbXApKTsKICAgIGNvbnZleEh1bGwgPSBtZXJnZShjb252ZXhIdWxsLCBuZXcgTm9kZShwb2ludCkpOwogIH0KICByZXR1cm4gdHJ1ZTsKfQogClBvaW50VHlwZSByb3RhdGUoUG9pbnRUeXBlIHBvaW50LCBQcmVjaXNpb25UeXBlIGFuZykgewogIHJldHVybiBQb2ludFR5cGUocG9pbnQuZmlyc3QgKiBjb3NsKGFuZykgKyBwb2ludC5zZWNvbmQgKiBzaW5sKGFuZyksIC1wb2ludC5maXJzdCAqIHNpbmwoYW5nKSArIHBvaW50LnNlY29uZCAqIGNvc2woYW5nKSk7Cn0KIAp2b2lkIG1ha2VDaGFuZ2UoTm9kZSAqJnVwQ29udmV4SHVsbCwKICAgICAgICAgICBOb2RlIComZG93bkNvbnZleEh1bGwsCiAgICAgICAgICAgdmVjdG9yIDwgcGFpciA8IFBvaW50VHlwZSwgTm9kZSogPiA+ICZ1cENoYW5nZXMsCiAgICAgICAgICAgdmVjdG9yIDwgcGFpciA8IFBvaW50VHlwZSwgTm9kZSogPiA+ICZkb3duQ2hhbmdlcywKICAgICAgICAgICBQb2ludFR5cGUgcG9pbnQpIHsKICBhZGRQb2ludCh1cENoYW5nZXMsIHVwQ29udmV4SHVsbCwgcG9pbnQsIHRydWUsIHVwY3cpOwogIGFkZFBvaW50KGRvd25DaGFuZ2VzLCBkb3duQ29udmV4SHVsbCwgcG9pbnQsIGZhbHNlLCBkd2N3KTsKfQogCnZvaWQgcm9sbGJhY2soTm9kZSAqJmNvbnZleEh1bGwsIHZlY3RvciA8IHBhaXIgPCBQb2ludFR5cGUsIE5vZGUqID4gPiAmcm9sbCwgaW50IG9sZFNpemUpIHsKICB3aGlsZSAocm9sbC5zaXplKCkgPiBvbGRTaXplKSB7CiAgICBQb2ludFR5cGUgY3VyID0gcm9sbC5iYWNrKCkuZmlyc3Q7CiAgICBOb2RlICp0cmVlID0gcm9sbC5iYWNrKCkuc2Vjb25kOwogICAgTm9kZSAqYSwgKmI7CiAgICBzcGxpdChjb252ZXhIdWxsLCBjb252ZXhIdWxsLCBhLCBtYWtlX3BhaXIoY3VyLmZpcnN0IC0gMWUtMTAsIGN1ci5zZWNvbmQpKTsKICAgIHNwbGl0KGEsIGEsIGIsIG1ha2VfcGFpcihjdXIuZmlyc3QgKyAxZS0xMCwgY3VyLnNlY29uZCkpOwogICAgY29udmV4SHVsbCA9IG1lcmdlKGNvbnZleEh1bGwsIG1lcmdlKHRyZWUsIGIpKTsKICAgIHJvbGwucG9wX2JhY2soKTsKICB9Cn0KIAp2b2lkIHNvbHZlKE5vZGUgKiZ1cENvbnZleEh1bGwsCiAgICAgICAgICAgTm9kZSAqJmRvd25Db252ZXhIdWxsLAogICAgICAgICAgIHZlY3RvciA8IHBhaXIgPCBQb2ludFR5cGUsIE5vZGUqID4gPiAmdXBDaGFuZ2VzLAogICAgICAgICAgIHZlY3RvciA8IHBhaXIgPCBQb2ludFR5cGUsIE5vZGUqID4gPiAmZG93bkNoYW5nZXMsCiAgICAgICAgICAgdmVjdG9yIDwgcGFpciA8IGNoYXIsIFBvaW50VHlwZSA+ID4gJnF1ZXJpZXMsCiAgICAgICAgICAgdmVjdG9yIDwgaW50ID4gJndhZGQsCiAgICAgICAgICAgdmVjdG9yIDwgaW50ID4gJnBhaXJlZCwKICAgICAgICAgICB2ZWN0b3IgPCBQcmVjaXNpb25UeXBlID4gJmFuc3dlcnMsCiAgICAgICAgICAgaW50IGxib3VuZCwgaW50IHJib3VuZCkgewogIGludCBtaWRkbGUgPSAobGJvdW5kICsgcmJvdW5kKSAvIDI7CiAgaW50IHVwY2ggPSB1cENoYW5nZXMuc2l6ZSgpLCBkd2NoID0gZG93bkNoYW5nZXMuc2l6ZSgpOwogIHZlY3RvciA8IGludCA+IG5hZGQ7CiAgZm9yIChpbnQgaSA9IDA7IGkgPCAoaW50KXdhZGQuc2l6ZSgpOyArK2kpIHsKICAgIGludCBsID0gd2FkZFtpXSwgciA9IHBhaXJlZFtsXTsKICAgIGlmIChyIDwgbGJvdW5kIHx8IGwgPiByYm91bmQpIHsKICAgICAgY29udGludWU7CiAgICB9CiAgICBpZiAobCA8PSBsYm91bmQgJiYgciA+IHJib3VuZCkgewogICAgICBtYWtlQ2hhbmdlKHVwQ29udmV4SHVsbCwgZG93bkNvbnZleEh1bGwsIHVwQ2hhbmdlcywgZG93bkNoYW5nZXMsIHF1ZXJpZXNbbF0uc2Vjb25kKTsKICAgICAgY29udGludWU7CiAgICB9CiAgICBuYWRkLnB1c2hfYmFjayh3YWRkW2ldKTsKICB9CiAgaWYgKGxib3VuZCAhPSByYm91bmQpIHsKICAgIHNvbHZlKHVwQ29udmV4SHVsbCwgZG93bkNvbnZleEh1bGwsIHVwQ2hhbmdlcywgZG93bkNoYW5nZXMsIHF1ZXJpZXMsIG5hZGQsIHBhaXJlZCwgYW5zd2VycywgbGJvdW5kLCBtaWRkbGUpOwogICAgc29sdmUodXBDb252ZXhIdWxsLCBkb3duQ29udmV4SHVsbCwgdXBDaGFuZ2VzLCBkb3duQ2hhbmdlcywgcXVlcmllcywgbmFkZCwgcGFpcmVkLCBhbnN3ZXJzLCBtaWRkbGUgKyAxLCByYm91bmQpOwogIH0gZWxzZSB7CiAgICBhbnN3ZXJzW2xib3VuZF0gPSBhYnMoKGdldFNxdWFyZSh1cENvbnZleEh1bGwpIC0gZ2V0U3F1YXJlKGRvd25Db252ZXhIdWxsKSkgLyAyLjApOwogIH0KICByb2xsYmFjayh1cENvbnZleEh1bGwsIHVwQ2hhbmdlcywgdXBjaCk7CiAgcm9sbGJhY2soZG93bkNvbnZleEh1bGwsIGRvd25DaGFuZ2VzLCBkd2NoKTsKfQogCnZlY3RvciA8IFByZWNpc2lvblR5cGUgPiBzb2x2ZVNtYXJ0KHZlY3RvciA8IHBhaXIgPCBjaGFyLCBQb2ludFR5cGUgPiA+IHF1ZXJpZXMpIHsKICBpbnQgcSA9IChpbnQpcXVlcmllcy5zaXplKCk7CiAgbWFwIDwgUG9pbnRUeXBlLCB2ZWN0b3IgPCBpbnQgPiA+IGY7CiAgdmVjdG9yIDwgaW50ID4gcGFpcmVkKHEpOwogIGZvciAoaW50IGkgPSAwOyBpIDwgcTsgKytpKSB7CiAgICBjaGFyIHR5cGUgPSBxdWVyaWVzW2ldLmZpcnN0OwogICAgUG9pbnRUeXBlIHBvaW50ID0gcXVlcmllc1tpXS5zZWNvbmQ7CiAgICBpZiAodHlwZSA9PSAnKycpIHsKICAgICAgZltwb2ludF0ucHVzaF9iYWNrKGkpOwogICAgfSBlbHNlIHsKICAgICAgaW50IHdoZXJlID0gZltwb2ludF0uYmFjaygpOwogICAgICBmW3BvaW50XS5wb3BfYmFjaygpOwogICAgICBwYWlyZWRbd2hlcmVdID0gaTsKICAgICAgcGFpcmVkW2ldID0gd2hlcmU7CiAgICB9CiAgfQogIHZlY3RvciA8IGludCA+IHdhZGQ7CiAgZm9yIChpbnQgaSA9IDA7IGkgPCBxOyArK2kpIHsKICAgIGNoYXIgdHlwZSA9IHF1ZXJpZXNbaV0uZmlyc3Q7CiAgICBQb2ludFR5cGUgcG9pbnQgPSBxdWVyaWVzW2ldLnNlY29uZDsKICAgIGlmICh0eXBlID09ICcrJykgewogICAgICB3YWRkLnB1c2hfYmFjayhpKTsKICAgIH0KICAgIGlmICh0eXBlID09ICctJyB8fCBmW3BvaW50XS5lbXB0eSgpKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgZm9yIChpbnQgaiA9IDA7IGogPCAoaW50KWZbcG9pbnRdLnNpemUoKTsgKytqKSB7CiAgICAgIGludCB3aGVyZSA9IGZbcG9pbnRdW2pdOwogICAgICBwYWlyZWRbd2hlcmVdID0gcTsKICAgIH0KICAgIGZbcG9pbnRdLmNsZWFyKCk7CiAgfQogIHZlY3RvciA8IFByZWNpc2lvblR5cGUgPiBhbnMocSk7CiAgTm9kZSAqdXBDb252ZXhIdWxsID0gTlVMTCwgKmRvd25Db252ZXhIdWxsID0gTlVMTDsKICB2ZWN0b3IgPCBwYWlyIDwgUG9pbnRUeXBlLCBOb2RlKiA+ID4gdXBDaGFuZ2VzLCBkb3duQ2hhbmdlczsKICBzb2x2ZSh1cENvbnZleEh1bGwsIGRvd25Db252ZXhIdWxsLCB1cENoYW5nZXMsIGRvd25DaGFuZ2VzLCBxdWVyaWVzLCB3YWRkLCBwYWlyZWQsIGFucywgMCwgcSAtIDEpOwogIHJldHVybiBhbnM7Cn0KIApuYW1lc3BhY2Ugc3R1cGlkIHsKICB2ZWN0b3IgPCBQb2ludFR5cGUgPiBjb252ZXhIdWxsKHZlY3RvciA8IFBvaW50VHlwZSA+IHBvaW50cykgewogICAgc29ydChwb2ludHMuYmVnaW4oKSwgcG9pbnRzLmVuZCgpKTsKICAgIGlmIChwb2ludHMuc2l6ZSgpIDwgMykgewogICAgICByZXR1cm4gcG9pbnRzOwogICAgfQogICAgdmVjdG9yIDwgUG9pbnRUeXBlID4gdXAsIGRvd247CiAgICB1cC5wdXNoX2JhY2socG9pbnRzWzBdKTsKICAgIGRvd24ucHVzaF9iYWNrKHBvaW50c1swXSk7CiAgICBmb3IgKGludCBpID0gMTsgaSA8IChpbnQpcG9pbnRzLnNpemUoKTsgKytpKSB7CiAgICAgIGlmIChpID09IChpbnQpcG9pbnRzLnNpemUoKSAtIDEgfHwgY3cocG9pbnRzWzBdLCBwb2ludHNbaV0sIHBvaW50cy5iYWNrKCkpID4gMCkgewogICAgICAgIHdoaWxlICh1cC5zaXplKCkgPj0gMiAmJiBjdyh1cFt1cC5zaXplKCkgLSAyXSwgdXBbdXAuc2l6ZSgpIC0gMV0sIHBvaW50c1tpXSkgPD0gMCkgewogICAgICAgICAgdXAucG9wX2JhY2soKTsKICAgICAgICB9CiAgICAgICAgdXAucHVzaF9iYWNrKHBvaW50c1tpXSk7CiAgICAgIH0KICAgICAgaWYgKGkgPT0gKGludClwb2ludHMuc2l6ZSgpIC0gMSB8fCBjdyhwb2ludHNbMF0sIHBvaW50c1tpXSwgcG9pbnRzLmJhY2soKSkgPCAwKSB7CiAgICAgICAgd2hpbGUgKGRvd24uc2l6ZSgpID49IDIgJiYgY3coZG93bltkb3duLnNpemUoKSAtIDJdLCBkb3duW2Rvd24uc2l6ZSgpIC0gMV0sIHBvaW50c1tpXSkgPj0gMCkgewogICAgICAgICAgZG93bi5wb3BfYmFjaygpOwogICAgICAgIH0KICAgICAgICBkb3duLnB1c2hfYmFjayhwb2ludHNbaV0pOwogICAgICB9CiAgICB9CiAgICB2ZWN0b3IgPCBQb2ludFR5cGUgPiByZXM7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IChpbnQpdXAuc2l6ZSgpOyArK2kpIHsKICAgICAgcmVzLnB1c2hfYmFjayh1cFtpXSk7CiAgICB9CiAgICBmb3IgKGludCBpID0gKGludClkb3duLnNpemUoKSAtIDI7IGkgPiAwOyAtLWkpIHsKICAgICAgcmVzLnB1c2hfYmFjayhkb3duW2ldKTsKICAgIH0KICAgIHJldHVybiByZXM7CiAgfQogCiAgdm9pZCBzb2x2ZSh2ZWN0b3IgPCBwYWlyIDwgY2hhciwgUG9pbnRUeXBlID4gPiBxdWVyaWVzKSB7CiAgICBtdWx0aXNldCA8IFBvaW50VHlwZSA+IHBvaW50czsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgKGludClxdWVyaWVzLnNpemUoKTsgKytpKSB7CiAgICAgIFBvaW50VHlwZSBwb2ludCA9IHF1ZXJpZXNbaV0uc2Vjb25kOwogICAgICBpZiAocXVlcmllc1tpXS5maXJzdCA9PSAnKycpIHsKICAgICAgICBwb2ludHMuaW5zZXJ0KHBvaW50KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAocG9pbnRzLmZpbmQocG9pbnQpICE9IHBvaW50cy5lbmQoKSkgewogICAgICAgICAgcG9pbnRzLmVyYXNlKHBvaW50cy5maW5kKHBvaW50KSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIFByZWNpc2lvblR5cGUgYW5zID0gMDsKICAgICAgaWYgKHBvaW50cy5zaXplKCkgPj0gMykgewogICAgICAgIHZlY3RvciA8IFBvaW50VHlwZSA+IHYocG9pbnRzLmJlZ2luKCksIHBvaW50cy5lbmQoKSk7CiAgICAgICAgdiA9IGNvbnZleEh1bGwodik7CiAgICAgICAgaWYgKHYuc2l6ZSgpID49IDMpIHsKICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgKGludCl2LnNpemUoKTsgKytpKSB7CiAgICAgICAgICAgIGFucyArPSAoUHJlY2lzaW9uVHlwZSkodltpXS5maXJzdCAtIHZbKGkgKyAxKSAlIHYuc2l6ZSgpXS5maXJzdCkgKiAodltpXS5zZWNvbmQgKyB2WyhpICsgMSkgJSB2LnNpemUoKV0uc2Vjb25kKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgbG9uZyBsb25nIHJlcyA9IChhbnMgPj0gMCA/IChsb25nIGxvbmcpKGFucyArIDAuNSkgOiAobG9uZyBsb25nKShhbnMgLSAwLjUpKTsKICAgICAgcHJpbnRmKCIlbGxkLiVsbGRcbiIsIGFicyhyZXMpIC8gMiwgYWJzKHJlcykgJSAyICogNSk7CiAgICB9CiAgfQp9OwogCmludCBtYWluKCkgewogLy8gZnJlb3BlbigiaW5wdXQudHh0IiwgInIiLCBzdGRpbik7CiAvLyBmcmVvcGVuKCJvdXRwdXQudHh0IiwgInciLCBzdGRvdXQpOwogIGludCB0OwogIHNjYW5mKCIlZCIsICZ0KTsKICB3aGlsZSAodCAtLT4gMCkgewogICAgaW50IHE7CiAgICBzY2FuZigiJWQiLCAmcSk7CiAgICB2ZWN0b3IgPCBwYWlyIDwgY2hhciwgUG9pbnRUeXBlID4gPiBxdWVyaWVzKHEpOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBxOyArK2kpIHsKICAgICAgaW50IHgsIHk7CiAgICAgIHNjYW5mKCJcbiVjJWQlZCIsICZxdWVyaWVzW2ldLmZpcnN0LCAmeCwgJnkpOwogICAgICBxdWVyaWVzW2ldLnNlY29uZC5maXJzdCA9IHg7CiAgICAgIHF1ZXJpZXNbaV0uc2Vjb25kLnNlY29uZCA9IHk7CiAgICB9Ci8vICAgIHN0dXBpZDo6c29sdmUocXVlcmllcyk7Ci8vICAgIGV4aXQoMCk7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IHE7ICsraSkgewogICAgICBxdWVyaWVzW2ldLnNlY29uZCA9IHJvdGF0ZShxdWVyaWVzW2ldLnNlY29uZCwgKzEzLjApOwogICAgfQogICAgdmVjdG9yIDwgUHJlY2lzaW9uVHlwZSA+IGFucyA9IHNvbHZlU21hcnQocXVlcmllcyk7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IChpbnQpYW5zLnNpemUoKTsgKytpKSB7CiAgICAgIHByaW50ZigiJS4xbGZcbiIsIChkb3VibGUpYW5zW2ldKTsKICAgIH0KICB9CiAgcmV0dXJuIDA7Cn0KICA=