#include <cstdio>
#include <vector>
using namespace std;
#define root 0
#define N 10100
#define LN 14
vector <int> adj[N], costs[N], indexx[N];
int baseArray[N], ptr;
int chainNo, chainInd[N], chainHead[N], posInBase[N];
int depth[N], pa[LN][N], otherEnd[N], subsize[N];
int st[N*6], qt[N*6];
/*
* make_tree:
* Used to construct the segment tree. It uses the baseArray for construction
*/
void make_tree(int cur, int s, int e) {
if(s == e-1) {
st[cur] = baseArray[s];
return;
}
int c1 = (cur<<1), c2 = c1 | 1, m = (s+e)>>1;
make_tree(c1, s, m);
make_tree(c2, m, e);
st[cur] = st[c1] > st[c2] ? st[c1] : st[c2];
}
/*
* update_tree:
* Point update. Update a single element of the segment tree.
*/
void update_tree(int cur, int s, int e, int x, int val) {
if(s > x || e <= x) return;
if(s == x && s == e-1) {
st[cur] = val;
return;
}
int c1 = (cur<<1), c2 = c1 | 1, m = (s+e)>>1;
update_tree(c1, s, m, x, val);
update_tree(c2, m, e, x, val);
st[cur] = st[c1] > st[c2] ? st[c1] : st[c2];
}
/*
* query_tree:
* Given S and E, it will return the maximum value in the range [S,E)
*/
void query_tree(int cur, int s, int e, int S, int E) {
if(s >= E || e <= S) {
qt[cur] = -1;
return;
}
if(s >= S && e <= E) {
qt[cur] = st[cur];
return;
}
int c1 = (cur<<1), c2 = c1 | 1, m = (s+e)>>1;
query_tree(c1, s, m, S, E);
query_tree(c2, m, e, S, E);
qt[cur] = qt[c1] > qt[c2] ? qt[c1] : qt[c2];
}
/*
* query_up:
* It takes two nodes u and v, condition is that v is an ancestor of u
* We query the chain in which u is present till chain head, then move to next chain up
* We do that way till u and v are in the same chain, we query for that part of chain and break
*/
int query_up(int u, int v) {
if(u == v) return 0; // Trivial
int uchain, vchain = chainInd[v], ans = -1;
// uchain and vchain are chain numbers of u and v
while(1) {
uchain = chainInd[u];
if(uchain == vchain) {
// Both u and v are in the same chain, so we need to query from u to v, update answer and break.
// We break because we came from u up till v, we are done
if(u==v) break;
query_tree(1, 0, ptr, posInBase[v]+1, posInBase[u]+1);
// Above is call to segment tree query function
if(qt[1] > ans) ans = qt[1]; // Update answer
break;
}
query_tree(1, 0, ptr, posInBase[chainHead[uchain]], posInBase[u]+1);
// Above is call to segment tree query function. We do from chainHead of u till u. That is the whole chain from
// start till head. We then update the answer
if(qt[1] > ans) ans = qt[1];
u = chainHead[uchain]; // move u to u's chainHead
u = pa[0][u]; //Then move to its parent, that means we changed chains
}
return ans;
}
/*
* LCA:
* Takes two nodes u, v and returns Lowest Common Ancestor of u, v
*/
int LCA(int u, int v) {
while(chainInd[u] != chainInd[v]){
if (depth[chainHead[chainInd[u]]] > depth[chainHead[chainInd[v]]])
u = pa[0][chainHead[chainInd[u]]];
else
v = pa[0][chainHead[chainInd[v]]];
}
if(depth[u] > depth[v])
return v;
return u;
}
void query(int u, int v) {
/*
* We have a query from u to v, we break it into two queries, u to LCA(u,v) and LCA(u,v) to v
*/
int lca = LCA(u, v);
int ans = query_up(u, lca); // One part of path
int temp = query_up(v, lca); // another part of path
if(temp > ans) ans = temp; // take the maximum of both paths
printf("%d\n", ans);
}
/*
* change:
* We just need to find its position in segment tree and update it
*/
void change(int i, int val) {
int u = otherEnd[i];
update_tree(1, 0, ptr, posInBase[u], val);
}
/*
* Actual HL-Decomposition part
* Initially all entries of chainHead[] are set to -1.
* So when ever a new chain is started, chain head is correctly assigned.
* As we add a new node to chain, we will note its position in the baseArray.
* In the first for loop we find the child node which has maximum sub-tree size.
* The following if condition is failed for leaf nodes.
* When the if condition passes, we expand the chain to special child.
* In the second for loop we recursively call the function on all normal nodes.
* chainNo++ ensures that we are creating a new chain for each normal child.
*/
void HLD(int curNode, int cost, int prev) {
if(chainHead[chainNo] == -1) {
chainHead[chainNo] = curNode; // Assign chain head
}
chainInd[curNode] = chainNo;
posInBase[curNode] = ptr; // Position of this node in baseArray which we will use in Segtree
baseArray[ptr++] = cost;
int sc = -1, ncost;
// Loop to find special child
for(int i=0; i<adj[curNode].size(); i++) if(adj[curNode][i] != prev) {
if(sc == -1 || subsize[sc] < subsize[adj[curNode][i]]) {
sc = adj[curNode][i];
ncost = costs[curNode][i];
}
}
if(sc != -1) {
// Expand the chain
HLD(sc, ncost, curNode);
for(int i=0; i<adj[curNode].size(); i++) if(adj[curNode][i] != prev) {
if(sc != adj[curNode][i]) {
// New chains at each normal node
chainNo++;
HLD(adj[curNode][i], costs[curNode][i], curNode);
}
}
}
}
/*
* dfs used to set parent of a node, depth of a node, subtree size of a node
*/
void dfs(int cur, int prev, int _depth=0) {
pa[0][cur] = prev;
depth[cur] = _depth;
subsize[cur] = 1;
for(int i=0; i<adj[cur].size(); i++)
if(adj[cur][i] != prev) {
otherEnd[indexx[cur][i]] = adj[cur][i];
dfs(adj[cur][i], cur, _depth+1);
subsize[cur] += subsize[adj[cur][i]];
}
}
int main() {
int t;
scanf("%d ", &t);
while(t--) {
ptr = 0;
int n;
scanf("%d", &n);
// Cleaning step, new test case
for(int i=0; i<n; i++) {
adj[i].clear();
costs[i].clear();
indexx[i].clear();
chainHead[i] = -1;
for(int j=0; j<LN; j++) pa[j][i] = -1;
}
for(int i=1; i<n; i++) {
int u, v, c;
scanf("%d %d %d", &u, &v, &c);
u--; v--;
adj[u].push_back(v);
costs[u].push_back(c);
indexx[u].push_back(i-1);
adj[v].push_back(u);
costs[v].push_back(c);
indexx[v].push_back(i-1);
}
chainNo = 0;
dfs(root, -1); // We set up subsize, depth and parent for each node
HLD(root, -1, -1); // We decomposed the tree and created baseArray
make_tree(1, 0, ptr); // We use baseArray and construct the needed segment tree
while(1) {
char s[100];
scanf("%s", s);
if(s[0]=='D') {
break;
}
int a, b;
scanf("%d %d", &a, &b);
if(s[0]=='Q') {
query(a-1, b-1);
} else {
change(a-1, b);
}
}
}
}
I2luY2x1ZGUgPGNzdGRpbz4KI2luY2x1ZGUgPHZlY3Rvcj4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCiNkZWZpbmUgcm9vdCAwCiNkZWZpbmUgTiAxMDEwMAojZGVmaW5lIExOIDE0Cgp2ZWN0b3IgPGludD4gYWRqW05dLCBjb3N0c1tOXSwgaW5kZXh4W05dOwppbnQgYmFzZUFycmF5W05dLCBwdHI7CmludCBjaGFpbk5vLCBjaGFpbkluZFtOXSwgY2hhaW5IZWFkW05dLCBwb3NJbkJhc2VbTl07CmludCBkZXB0aFtOXSwgcGFbTE5dW05dLCBvdGhlckVuZFtOXSwgc3Vic2l6ZVtOXTsKaW50IHN0W04qNl0sIHF0W04qNl07CgovKgogKiBtYWtlX3RyZWU6CiAqIFVzZWQgdG8gY29uc3RydWN0IHRoZSBzZWdtZW50IHRyZWUuIEl0IHVzZXMgdGhlIGJhc2VBcnJheSBmb3IgY29uc3RydWN0aW9uCiAqLwp2b2lkIG1ha2VfdHJlZShpbnQgY3VyLCBpbnQgcywgaW50IGUpIHsKCWlmKHMgPT0gZS0xKSB7CgkJc3RbY3VyXSA9IGJhc2VBcnJheVtzXTsKCQlyZXR1cm47Cgl9CglpbnQgYzEgPSAoY3VyPDwxKSwgYzIgPSBjMSB8IDEsIG0gPSAocytlKT4+MTsKCW1ha2VfdHJlZShjMSwgcywgbSk7CgltYWtlX3RyZWUoYzIsIG0sIGUpOwoJc3RbY3VyXSA9IHN0W2MxXSA+IHN0W2MyXSA/IHN0W2MxXSA6IHN0W2MyXTsKfQoKLyoKICogdXBkYXRlX3RyZWU6CiAqIFBvaW50IHVwZGF0ZS4gVXBkYXRlIGEgc2luZ2xlIGVsZW1lbnQgb2YgdGhlIHNlZ21lbnQgdHJlZS4KICovCnZvaWQgdXBkYXRlX3RyZWUoaW50IGN1ciwgaW50IHMsIGludCBlLCBpbnQgeCwgaW50IHZhbCkgewoJaWYocyA+IHggfHwgZSA8PSB4KSByZXR1cm47CglpZihzID09IHggJiYgcyA9PSBlLTEpIHsKCQlzdFtjdXJdID0gdmFsOwoJCXJldHVybjsKCX0KCWludCBjMSA9IChjdXI8PDEpLCBjMiA9IGMxIHwgMSwgbSA9IChzK2UpPj4xOwoJdXBkYXRlX3RyZWUoYzEsIHMsIG0sIHgsIHZhbCk7Cgl1cGRhdGVfdHJlZShjMiwgbSwgZSwgeCwgdmFsKTsKCXN0W2N1cl0gPSBzdFtjMV0gPiBzdFtjMl0gPyBzdFtjMV0gOiBzdFtjMl07Cn0KCi8qCiAqIHF1ZXJ5X3RyZWU6CiAqIEdpdmVuIFMgYW5kIEUsIGl0IHdpbGwgcmV0dXJuIHRoZSBtYXhpbXVtIHZhbHVlIGluIHRoZSByYW5nZSBbUyxFKQogKi8Kdm9pZCBxdWVyeV90cmVlKGludCBjdXIsIGludCBzLCBpbnQgZSwgaW50IFMsIGludCBFKSB7CglpZihzID49IEUgfHwgZSA8PSBTKSB7CgkJcXRbY3VyXSA9IC0xOwoJCXJldHVybjsKCX0KCWlmKHMgPj0gUyAmJiBlIDw9IEUpIHsKCQlxdFtjdXJdID0gc3RbY3VyXTsKCQlyZXR1cm47Cgl9CglpbnQgYzEgPSAoY3VyPDwxKSwgYzIgPSBjMSB8IDEsIG0gPSAocytlKT4+MTsKCXF1ZXJ5X3RyZWUoYzEsIHMsIG0sIFMsIEUpOwoJcXVlcnlfdHJlZShjMiwgbSwgZSwgUywgRSk7CglxdFtjdXJdID0gcXRbYzFdID4gcXRbYzJdID8gcXRbYzFdIDogcXRbYzJdOwp9CgovKgogKiBxdWVyeV91cDoKICogSXQgdGFrZXMgdHdvIG5vZGVzIHUgYW5kIHYsIGNvbmRpdGlvbiBpcyB0aGF0IHYgaXMgYW4gYW5jZXN0b3Igb2YgdQogKiBXZSBxdWVyeSB0aGUgY2hhaW4gaW4gd2hpY2ggdSBpcyBwcmVzZW50IHRpbGwgY2hhaW4gaGVhZCwgdGhlbiBtb3ZlIHRvIG5leHQgY2hhaW4gdXAKICogV2UgZG8gdGhhdCB3YXkgdGlsbCB1IGFuZCB2IGFyZSBpbiB0aGUgc2FtZSBjaGFpbiwgd2UgcXVlcnkgZm9yIHRoYXQgcGFydCBvZiBjaGFpbiBhbmQgYnJlYWsKICovCgppbnQgcXVlcnlfdXAoaW50IHUsIGludCB2KSB7CglpZih1ID09IHYpIHJldHVybiAwOyAvLyBUcml2aWFsCglpbnQgdWNoYWluLCB2Y2hhaW4gPSBjaGFpbkluZFt2XSwgYW5zID0gLTE7CgkvLyB1Y2hhaW4gYW5kIHZjaGFpbiBhcmUgY2hhaW4gbnVtYmVycyBvZiB1IGFuZCB2Cgl3aGlsZSgxKSB7CgkJdWNoYWluID0gY2hhaW5JbmRbdV07CgkJaWYodWNoYWluID09IHZjaGFpbikgewoJCQkvLyBCb3RoIHUgYW5kIHYgYXJlIGluIHRoZSBzYW1lIGNoYWluLCBzbyB3ZSBuZWVkIHRvIHF1ZXJ5IGZyb20gdSB0byB2LCB1cGRhdGUgYW5zd2VyIGFuZCBicmVhay4KCQkJLy8gV2UgYnJlYWsgYmVjYXVzZSB3ZSBjYW1lIGZyb20gdSB1cCB0aWxsIHYsIHdlIGFyZSBkb25lCgkJCWlmKHU9PXYpIGJyZWFrOwoJCQlxdWVyeV90cmVlKDEsIDAsIHB0ciwgcG9zSW5CYXNlW3ZdKzEsIHBvc0luQmFzZVt1XSsxKTsKCQkJLy8gQWJvdmUgaXMgY2FsbCB0byBzZWdtZW50IHRyZWUgcXVlcnkgZnVuY3Rpb24KCQkJaWYocXRbMV0gPiBhbnMpIGFucyA9IHF0WzFdOyAvLyBVcGRhdGUgYW5zd2VyCgkJCWJyZWFrOwoJCX0KCQlxdWVyeV90cmVlKDEsIDAsIHB0ciwgcG9zSW5CYXNlW2NoYWluSGVhZFt1Y2hhaW5dXSwgcG9zSW5CYXNlW3VdKzEpOwoJCS8vIEFib3ZlIGlzIGNhbGwgdG8gc2VnbWVudCB0cmVlIHF1ZXJ5IGZ1bmN0aW9uLiBXZSBkbyBmcm9tIGNoYWluSGVhZCBvZiB1IHRpbGwgdS4gVGhhdCBpcyB0aGUgd2hvbGUgY2hhaW4gZnJvbQoJCS8vIHN0YXJ0IHRpbGwgaGVhZC4gV2UgdGhlbiB1cGRhdGUgdGhlIGFuc3dlcgoJCWlmKHF0WzFdID4gYW5zKSBhbnMgPSBxdFsxXTsKCQl1ID0gY2hhaW5IZWFkW3VjaGFpbl07IC8vIG1vdmUgdSB0byB1J3MgY2hhaW5IZWFkCgkJdSA9IHBhWzBdW3VdOyAvL1RoZW4gbW92ZSB0byBpdHMgcGFyZW50LCB0aGF0IG1lYW5zIHdlIGNoYW5nZWQgY2hhaW5zCgl9CglyZXR1cm4gYW5zOwp9CgovKgogKiBMQ0E6CiAqIFRha2VzIHR3byBub2RlcyB1LCB2IGFuZCByZXR1cm5zIExvd2VzdCBDb21tb24gQW5jZXN0b3Igb2YgdSwgdgogKi8KaW50IExDQShpbnQgdSwgaW50IHYpIHsKCQoJd2hpbGUoY2hhaW5JbmRbdV0gIT0gY2hhaW5JbmRbdl0pewoJCQoJCWlmIChkZXB0aFtjaGFpbkhlYWRbY2hhaW5JbmRbdV1dXSA+IGRlcHRoW2NoYWluSGVhZFtjaGFpbkluZFt2XV1dKQoJCQl1ID0gcGFbMF1bY2hhaW5IZWFkW2NoYWluSW5kW3VdXV07CgkJZWxzZQoJCQl2ID0gcGFbMF1bY2hhaW5IZWFkW2NoYWluSW5kW3ZdXV07CgkJCQoJfQoJCglpZihkZXB0aFt1XSA+IGRlcHRoW3ZdKQoJCXJldHVybiB2OwoJcmV0dXJuIHU7Cgp9Cgp2b2lkIHF1ZXJ5KGludCB1LCBpbnQgdikgewoJLyoKCSAqIFdlIGhhdmUgYSBxdWVyeSBmcm9tIHUgdG8gdiwgd2UgYnJlYWsgaXQgaW50byB0d28gcXVlcmllcywgdSB0byBMQ0EodSx2KSBhbmQgTENBKHUsdikgdG8gdgoJICovCglpbnQgbGNhID0gTENBKHUsIHYpOwoJaW50IGFucyA9IHF1ZXJ5X3VwKHUsIGxjYSk7IC8vIE9uZSBwYXJ0IG9mIHBhdGgKCWludCB0ZW1wID0gcXVlcnlfdXAodiwgbGNhKTsgLy8gYW5vdGhlciBwYXJ0IG9mIHBhdGgKCWlmKHRlbXAgPiBhbnMpIGFucyA9IHRlbXA7IC8vIHRha2UgdGhlIG1heGltdW0gb2YgYm90aCBwYXRocwoJcHJpbnRmKCIlZFxuIiwgYW5zKTsKfQoKLyoKICogY2hhbmdlOgogKiBXZSBqdXN0IG5lZWQgdG8gZmluZCBpdHMgcG9zaXRpb24gaW4gc2VnbWVudCB0cmVlIGFuZCB1cGRhdGUgaXQKICovCnZvaWQgY2hhbmdlKGludCBpLCBpbnQgdmFsKSB7CglpbnQgdSA9IG90aGVyRW5kW2ldOwoJdXBkYXRlX3RyZWUoMSwgMCwgcHRyLCBwb3NJbkJhc2VbdV0sIHZhbCk7Cn0KCi8qCiAqIEFjdHVhbCBITC1EZWNvbXBvc2l0aW9uIHBhcnQKICogSW5pdGlhbGx5IGFsbCBlbnRyaWVzIG9mIGNoYWluSGVhZFtdIGFyZSBzZXQgdG8gLTEuCiAqIFNvIHdoZW4gZXZlciBhIG5ldyBjaGFpbiBpcyBzdGFydGVkLCBjaGFpbiBoZWFkIGlzIGNvcnJlY3RseSBhc3NpZ25lZC4KICogQXMgd2UgYWRkIGEgbmV3IG5vZGUgdG8gY2hhaW4sIHdlIHdpbGwgbm90ZSBpdHMgcG9zaXRpb24gaW4gdGhlIGJhc2VBcnJheS4KICogSW4gdGhlIGZpcnN0IGZvciBsb29wIHdlIGZpbmQgdGhlIGNoaWxkIG5vZGUgd2hpY2ggaGFzIG1heGltdW0gc3ViLXRyZWUgc2l6ZS4KICogVGhlIGZvbGxvd2luZyBpZiBjb25kaXRpb24gaXMgZmFpbGVkIGZvciBsZWFmIG5vZGVzLgogKiBXaGVuIHRoZSBpZiBjb25kaXRpb24gcGFzc2VzLCB3ZSBleHBhbmQgdGhlIGNoYWluIHRvIHNwZWNpYWwgY2hpbGQuCiAqIEluIHRoZSBzZWNvbmQgZm9yIGxvb3Agd2UgcmVjdXJzaXZlbHkgY2FsbCB0aGUgZnVuY3Rpb24gb24gYWxsIG5vcm1hbCBub2Rlcy4KICogY2hhaW5ObysrIGVuc3VyZXMgdGhhdCB3ZSBhcmUgY3JlYXRpbmcgYSBuZXcgY2hhaW4gZm9yIGVhY2ggbm9ybWFsIGNoaWxkLgogKi8Kdm9pZCBITEQoaW50IGN1ck5vZGUsIGludCBjb3N0LCBpbnQgcHJldikgewoJaWYoY2hhaW5IZWFkW2NoYWluTm9dID09IC0xKSB7CgkJY2hhaW5IZWFkW2NoYWluTm9dID0gY3VyTm9kZTsgLy8gQXNzaWduIGNoYWluIGhlYWQKCX0KCWNoYWluSW5kW2N1ck5vZGVdID0gY2hhaW5ObzsKCXBvc0luQmFzZVtjdXJOb2RlXSA9IHB0cjsgLy8gUG9zaXRpb24gb2YgdGhpcyBub2RlIGluIGJhc2VBcnJheSB3aGljaCB3ZSB3aWxsIHVzZSBpbiBTZWd0cmVlCgliYXNlQXJyYXlbcHRyKytdID0gY29zdDsKCglpbnQgc2MgPSAtMSwgbmNvc3Q7CgkvLyBMb29wIHRvIGZpbmQgc3BlY2lhbCBjaGlsZAoJZm9yKGludCBpPTA7IGk8YWRqW2N1ck5vZGVdLnNpemUoKTsgaSsrKSBpZihhZGpbY3VyTm9kZV1baV0gIT0gcHJldikgewoJCWlmKHNjID09IC0xIHx8IHN1YnNpemVbc2NdIDwgc3Vic2l6ZVthZGpbY3VyTm9kZV1baV1dKSB7CgkJCXNjID0gYWRqW2N1ck5vZGVdW2ldOwoJCQluY29zdCA9IGNvc3RzW2N1ck5vZGVdW2ldOwoJCX0KCX0KCglpZihzYyAhPSAtMSkgewoJCS8vIEV4cGFuZCB0aGUgY2hhaW4KCQlITEQoc2MsIG5jb3N0LCBjdXJOb2RlKTsKCgkJZm9yKGludCBpPTA7IGk8YWRqW2N1ck5vZGVdLnNpemUoKTsgaSsrKSBpZihhZGpbY3VyTm9kZV1baV0gIT0gcHJldikgewoJCQlpZihzYyAhPSBhZGpbY3VyTm9kZV1baV0pIHsKCQkJLy8gTmV3IGNoYWlucyBhdCBlYWNoIG5vcm1hbCBub2RlCgkJCQljaGFpbk5vKys7CgkJCQlITEQoYWRqW2N1ck5vZGVdW2ldLCBjb3N0c1tjdXJOb2RlXVtpXSwgY3VyTm9kZSk7CgkJCX0KCQl9Cgl9Cn0KCi8qCiAqIGRmcyB1c2VkIHRvIHNldCBwYXJlbnQgb2YgYSBub2RlLCBkZXB0aCBvZiBhIG5vZGUsIHN1YnRyZWUgc2l6ZSBvZiBhIG5vZGUKICovCnZvaWQgZGZzKGludCBjdXIsIGludCBwcmV2LCBpbnQgX2RlcHRoPTApIHsKCXBhWzBdW2N1cl0gPSBwcmV2OwoJZGVwdGhbY3VyXSA9IF9kZXB0aDsKCXN1YnNpemVbY3VyXSA9IDE7Cglmb3IoaW50IGk9MDsgaTxhZGpbY3VyXS5zaXplKCk7IGkrKykKCQlpZihhZGpbY3VyXVtpXSAhPSBwcmV2KSB7CgkJCW90aGVyRW5kW2luZGV4eFtjdXJdW2ldXSA9IGFkaltjdXJdW2ldOwoJCQlkZnMoYWRqW2N1cl1baV0sIGN1ciwgX2RlcHRoKzEpOwoJCQlzdWJzaXplW2N1cl0gKz0gc3Vic2l6ZVthZGpbY3VyXVtpXV07CgkJfQp9CgppbnQgbWFpbigpIHsKCWludCB0OwoJc2NhbmYoIiVkICIsICZ0KTsKCXdoaWxlKHQtLSkgewoJCXB0ciA9IDA7CgkJaW50IG47CgkJc2NhbmYoIiVkIiwgJm4pOwoJCS8vIENsZWFuaW5nIHN0ZXAsIG5ldyB0ZXN0IGNhc2UKCQlmb3IoaW50IGk9MDsgaTxuOyBpKyspIHsKCQkJYWRqW2ldLmNsZWFyKCk7CgkJCWNvc3RzW2ldLmNsZWFyKCk7CgkJCWluZGV4eFtpXS5jbGVhcigpOwoJCQljaGFpbkhlYWRbaV0gPSAtMTsKCQkJZm9yKGludCBqPTA7IGo8TE47IGorKykgcGFbal1baV0gPSAtMTsKCQl9CgkJZm9yKGludCBpPTE7IGk8bjsgaSsrKSB7CgkJCWludCB1LCB2LCBjOwoJCQlzY2FuZigiJWQgJWQgJWQiLCAmdSwgJnYsICZjKTsKCQkJdS0tOyB2LS07CgkJCWFkalt1XS5wdXNoX2JhY2sodik7CgkJCWNvc3RzW3VdLnB1c2hfYmFjayhjKTsKCQkJaW5kZXh4W3VdLnB1c2hfYmFjayhpLTEpOwoJCQlhZGpbdl0ucHVzaF9iYWNrKHUpOwoJCQljb3N0c1t2XS5wdXNoX2JhY2soYyk7CgkJCWluZGV4eFt2XS5wdXNoX2JhY2soaS0xKTsKCQl9CgoJCWNoYWluTm8gPSAwOwoJCWRmcyhyb290LCAtMSk7IC8vIFdlIHNldCB1cCBzdWJzaXplLCBkZXB0aCBhbmQgcGFyZW50IGZvciBlYWNoIG5vZGUKCQlITEQocm9vdCwgLTEsIC0xKTsgLy8gV2UgZGVjb21wb3NlZCB0aGUgdHJlZSBhbmQgY3JlYXRlZCBiYXNlQXJyYXkKCQltYWtlX3RyZWUoMSwgMCwgcHRyKTsgLy8gV2UgdXNlIGJhc2VBcnJheSBhbmQgY29uc3RydWN0IHRoZSBuZWVkZWQgc2VnbWVudCB0cmVlCgoJCXdoaWxlKDEpIHsKCQkJY2hhciBzWzEwMF07CgkJCXNjYW5mKCIlcyIsIHMpOwoJCQlpZihzWzBdPT0nRCcpIHsKCQkJCWJyZWFrOwoJCQl9CgkJCWludCBhLCBiOwoJCQlzY2FuZigiJWQgJWQiLCAmYSwgJmIpOwoJCQlpZihzWzBdPT0nUScpIHsKCQkJCXF1ZXJ5KGEtMSwgYi0xKTsKCQkJfSBlbHNlIHsKCQkJCWNoYW5nZShhLTEsIGIpOwoJCQl9CgkJfQoJfQp9