#include <bits/stdc++.h> // NeOWami
using namespace std;
#define ft first
#define sc second
using pii = pair<int, int>;
const int N = 150005;
int n, m, ans = 0;
vector<int> G[N];
struct Node {
int s, t, p;
};
Node a[N];
namespace sub1 {
vector<int> Gr[N];
int cnt[N], sum = 0;
void dfs(int u, int pre) {
for (int i: Gr[u]) {
cnt[i]++;
if (cnt[i] == 2) sum += a[i].p;
}
ans = max(ans, sum);
for (int v: G[u]) if (v != pre) {
dfs(v, u);
}
for (int i: Gr[u]) {
if (cnt[i] == 2) sum -= a[i].p;
cnt[i]--;
}
}
void solve() {
sum = 0;
fill(cnt + 1, cnt + m + 1, 0);
for (int i = 1; i <= m; i++) {
Gr[a[i].s].push_back(i);
Gr[a[i].t].push_back(i);
}
for (int i = 1; i <= n; i++) if (G[i].size() == 1) dfs(i, i);
cout << ans << '\n';
for (int i = 1; i <= n; i++) Gr[i].clear();
}
};
/*
sub 1:
Chọn mỗi đỉnh làm gốc và DFS:
Trong quá trình dfs sẽ lưu cnt[i] là số đỉnh của cặp truyền thông i xuất hiện trong đoạn từ root -> u
nếu cnt[i] == 2 thì sum += p
time complexity: O(N * (N + M))
*/
const int LG = 18;
int tin[N], tout[N], stt;
int h[N], up[N][LG];
struct square {
int x1, x2, y1, y2, p;
};
vector<square> SQ;
void dfsInit(int u) {
}
inline bool insideTreeU(int u, int v) {
}
int jump(int u, int k){
}
int getDircetChildU(int u, int v) {
}
void init() {
}
namespace sub2 {
int ps[1005][1005];
void solve() {
init();
for (int i = 0; i <= n + 1; i++) for (int j = 0; j <= n + 1; j++) ps[i][j] = 0;
for (square sq: SQ) if (sq.x1 <= sq.x2 && sq.y1 <= sq.y2) {
ps[sq.x1][sq.y1] += sq.p;
ps[sq.x1][sq.y2 + 1] -= sq.p;
ps[sq.x2 + 1][sq.y1] -= sq.p;
ps[sq.x2 + 1][sq.y2 + 1] += sq.p;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
ps[i][j] = ps[i][j] + ps[i - 1][j] + ps[i][j - 1] - ps[i - 1][j - 1];
ans = max(ans, ps[i][j]);
}
}
cout << ans << "\n";
}
};
/*
*Lưu ý, solve đang viết cho trường hợp cặp truyền thông s và t khác nhau, (vì code mẫu nó thế =))), còn s == t thì chịu =))))
sub 2:
Dfs trải phẳng cây bằng Euler tour với gốc từ 1, lưu tin và tout
Xét cặp truyền thông s và t (đổi chỗ s, t để tin[s] <= tin[t] cho dễ xẻt):
*Các cặp đỉnh (x, y) (để x <= y cho dễ xét) sẽ thỏa mãn cặp truyền thông (s, t) khi cả đỉnh s và t nằm trên đường đi từ x->y
*Ngoài ra, những cặp đỉnh (x,y) thỏa mãn (s, t) đó sẽ tạo thành một/hai vùng chữ nhật như sau:
+ Case 1: s và t ở 2 nhánh khác nhau (s không phải là tổ tiên của t)
Khi đó x nằm trong cây con của s và y nằm trong cây con của t sẽ luôn thỏa mãn
⇒ Tạo ra hình chữ nhật: [tin[s], tout[s]] x [tin[t], tout[t]] với trọng số p
Xem hình ở đây cho dễ hiểu: https://f...content-available-to-author-only...e.host/i/K0Bj8zb
+ Case 2: s là tổ tiên của t
Gọi u là đứa con của s nằm trên đường s -> t. (dễ dàng tìm bằng binary lifting trong O(logN))
Muốn đường (x, y) chứa cả s và t thì một đầu mút phải ở trong cây con của t, còn đầu kia phải nằm ngoài cây con của u
(vì nếu đều ở trong thì đường không "chạm" tới s).
Do ta xét cặp x, y và đặt trục tung theo y là cây con của t, phần theo trục hoành là "ngoài cây con u" tách thành hai đoạn:
[1, tin[u]-1] và [tout[u]+1, N]
⇒ Tạo ra hai hình chữ nhật: [1, tin[u]-1] x [tin[t], tout[t]], [tout[u]+1,N] x [tin[t], tout[t]] với trọng số p.
Xem hình ở đây cho dễ hiểu: https://f...content-available-to-author-only...e.host/i/graph1758850484785.K0BVzMB
Ngoài ra do đã cố định x <= y, nên khi cài ta cũng cần đảo lại (hay push thêm) cặp(y, x);
Giờ đây chuyển sang bài toán:
Cho hình vuông N x N:
Cập nhập [x1->x2] x [y1->y2] lên p giá tị
Tìm max (x, y)
Với sub 2 N = 1e4
Ta có thể fill bằng prefix sum (tuy nhiên nếu vậy sẽ tốn bộ nhớ N * N).
Ngoài ra còn có thể cài sweepline nhưng update O (N)
time complexity: O(N * N + MlogN + NlogN)
Hoặc cài chia căn:
(n+m)n
time complexity: O((N + M)√(N) + MlogN + NlogN)
(Do lười nên code sẽ code dạng prefix sum fill đoạn)
*/
namespace sub3 {
int st[N * 4], lz[N * 4];
struct Edge {
int x1, x2, y, p;
};
vector<Edge> E;
void build(int id, int l, int r) {
}
void down(int id) {
}
void update(int id, int l, int r, int u, int v, int t) {
}
void solve() {
init();
cout << ans << "\n";
}
};
/*
sub 3:
Với N = 150000
Ta cập nhập bằng Duyệt quét (sweep-line) theo y + Cây đoạn (segment tree) 1D trên x
Mỗi hình chữ nhật [X1, X2] × [Y1, Y2] được tách thành hai sự kiện:
Mở tại y = Y₁: cộng +p cho khoảng x ∈ [X1, X2].
Đóng tại y = Y2 + 1: cộng -p cho khoảng x ∈ [x1, X2].
segtree lazy range add trực tiếp trên mảng giá trị A (A[x] = tổng trọng số đang phủ tại hoành độ x).
Mỗi sự kiện [x1,x2] là range add A[x1..x2]+=w; sau khi xử lý tất cả sự kiện của một y, lấy max(A)
Sau khi xử lý các sự kiện của y, cập nhật res = max(res, tree[1].max).
Kết luận: res chính là tổng lợi nhuận lớn nhất khi chọn một đường trên cây.
time complexity: O((N + M)logN)
*Ngoài ra có thể cài BIT2D nhưng không nên
*/
signed main() {
cin.tie(NULL)->sync_with_stdio(false);
if(ifstream("NETSRV.inp")) {
freopen("NETSRV.inp", "r", stdin);
freopen("NETSRV.out", "w", stdout);
}
int tt; cin >> tt;
while(tt--) {
cin >> n;
for (int i = 1; i < n; i++) {
int u, v; cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
cin >> m;
for (int i = 1; i <= m; i++) {
cin >> a[i].s >> a[i].t >> a[i].p;
}
// sub3::solve();
if (n <= 100) sub1::solve();
else if (n <= 1000) sub2::solve();
else sub3::solve();
for (int i = 1; i <= n; i++) G[i].clear();
ans = 0;
}
return 0;
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+IC8vIE5lT1dhbWkKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCiNkZWZpbmUgZnQgZmlyc3QKI2RlZmluZSBzYyBzZWNvbmQKdXNpbmcgcGlpID0gcGFpcjxpbnQsIGludD47CmNvbnN0IGludCBOID0gMTUwMDA1OwppbnQgbiwgbSwgYW5zID0gMDsKdmVjdG9yPGludD4gR1tOXTsKc3RydWN0IE5vZGUgewogICAgaW50IHMsIHQsIHA7Cn07Ck5vZGUgYVtOXTsKCm5hbWVzcGFjZSBzdWIxIHsKdmVjdG9yPGludD4gR3JbTl07CmludCBjbnRbTl0sIHN1bSA9IDA7CnZvaWQgZGZzKGludCB1LCBpbnQgcHJlKSB7CiAgICBmb3IgKGludCBpOiBHclt1XSkgewogICAgICAgIGNudFtpXSsrOwogICAgICAgIGlmIChjbnRbaV0gPT0gMikgc3VtICs9IGFbaV0ucDsKICAgIH0KICAgIGFucyA9IG1heChhbnMsIHN1bSk7CiAgICBmb3IgKGludCB2OiBHW3VdKSBpZiAodiAhPSBwcmUpIHsKICAgICAgICBkZnModiwgdSk7CiAgICB9CiAgICBmb3IgKGludCBpOiBHclt1XSkgewogICAgICAgIGlmIChjbnRbaV0gPT0gMikgc3VtIC09IGFbaV0ucDsKICAgICAgICBjbnRbaV0tLTsKICAgIH0KfQp2b2lkIHNvbHZlKCkgewogICAgc3VtID0gMDsKICAgIGZpbGwoY250ICsgMSwgY250ICsgbSArIDEsIDApOwogICAgZm9yIChpbnQgaSA9IDE7IGkgPD0gbTsgaSsrKSB7CiAgICAgICAgR3JbYVtpXS5zXS5wdXNoX2JhY2soaSk7CiAgICAgICAgR3JbYVtpXS50XS5wdXNoX2JhY2soaSk7CiAgICB9CiAgICBmb3IgKGludCBpID0gMTsgaSA8PSBuOyBpKyspIGlmIChHW2ldLnNpemUoKSA9PSAxKSBkZnMoaSwgaSk7CiAgICBjb3V0IDw8IGFucyA8PCAnXG4nOwogICAgZm9yIChpbnQgaSA9IDE7IGkgPD0gbjsgaSsrKSBHcltpXS5jbGVhcigpOwp9Cn07Ci8qCnN1YiAxOgpDaOG7jW4gbeG7l2kgxJHhu4luaCBsw6BtIGfhu5FjIHbDoCBERlM6ClRyb25nIHF1w6EgdHLDrG5oIGRmcyBz4bq9IGzGsHUgY250W2ldIGzDoCBz4buRIMSR4buJbmggY+G7p2EgY+G6t3AgdHJ1eeG7gW4gdGjDtG5nIGkgeHXhuqV0IGhp4buHbiB0cm9uZyDEkW/huqFuIHThu6sgcm9vdCAtPiB1Cm7hur91IGNudFtpXSA9PSAyIHRow6wgc3VtICs9IHAKdGltZSBjb21wbGV4aXR5OiBPKE4gKiAoTiArIE0pKQoqLwpjb25zdCBpbnQgTEcgPSAxODsKaW50IHRpbltOXSwgdG91dFtOXSwgc3R0OwppbnQgaFtOXSwgdXBbTl1bTEddOwpzdHJ1Y3Qgc3F1YXJlIHsKICAgIGludCB4MSwgeDIsIHkxLCB5MiwgcDsKfTsKdmVjdG9yPHNxdWFyZT4gU1E7CnZvaWQgZGZzSW5pdChpbnQgdSkgewp9CmlubGluZSBib29sIGluc2lkZVRyZWVVKGludCB1LCBpbnQgdikgewoKfQppbnQganVtcChpbnQgdSwgaW50IGspewp9CmludCBnZXREaXJjZXRDaGlsZFUoaW50IHUsIGludCB2KSB7Cgp9CnZvaWQgaW5pdCgpIHsKCn0KCm5hbWVzcGFjZSBzdWIyIHsKaW50IHBzWzEwMDVdWzEwMDVdOwp2b2lkIHNvbHZlKCkgewogICAgaW5pdCgpOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPD0gbiArIDE7IGkrKykgZm9yIChpbnQgaiA9IDA7IGogPD0gbiArIDE7IGorKykgcHNbaV1bal0gPSAwOwogICAgZm9yIChzcXVhcmUgc3E6IFNRKSBpZiAoc3EueDEgPD0gc3EueDIgJiYgc3EueTEgPD0gc3EueTIpIHsKICAgICAgICBwc1tzcS54MV1bc3EueTFdICs9IHNxLnA7CiAgICAgICAgcHNbc3EueDFdW3NxLnkyICsgMV0gLT0gc3EucDsKICAgICAgICBwc1tzcS54MiArIDFdW3NxLnkxXSAtPSBzcS5wOwogICAgICAgIHBzW3NxLngyICsgMV1bc3EueTIgKyAxXSArPSBzcS5wOwogICAgfQogICAgZm9yIChpbnQgaSA9IDE7IGkgPD0gbjsgaSsrKSB7CiAgICAgICAgZm9yIChpbnQgaiA9IDE7IGogPD0gbjsgaisrKSB7CiAgICAgICAgICAgIHBzW2ldW2pdID0gcHNbaV1bal0gKyBwc1tpIC0gMV1bal0gKyBwc1tpXVtqIC0gMV0gLSBwc1tpIC0gMV1baiAtIDFdOwogICAgICAgICAgICBhbnMgPSBtYXgoYW5zLCBwc1tpXVtqXSk7CiAgICAgICAgfQogICAgfQogICAgY291dCA8PCBhbnMgPDwgIlxuIjsKfQp9OwovKgoqTMawdSDDvSwgc29sdmUgxJFhbmcgdmnhur90IGNobyB0csaw4budbmcgaOG7o3AgY+G6t3AgdHJ1eeG7gW4gdGjDtG5nIHMgdsOgIHQga2jDoWMgbmhhdSwgKHbDrCBjb2RlIG3huqt1IG7DsyB0aOG6vyA9KSkpLCBjw7JuIHMgPT0gdCB0aMOsIGNo4buLdSA9KSkpKQoKc3ViIDI6CkRmcyB0cuG6o2kgcGjhurNuZyBjw6J5IGLhurFuZyBFdWxlciB0b3VyIHbhu5tpIGfhu5FjIHThu6sgMSwgbMawdSB0aW4gdsOgIHRvdXQKWMOpdCBj4bq3cCB0cnV54buBbiB0aMO0bmcgcyB2w6AgdCAoxJHhu5VpIGNo4buXIHMsIHQgxJHhu4MgdGluW3NdIDw9IHRpblt0XSBjaG8gZOG7hSB44bq7dCk6CipDw6FjIGPhurdwIMSR4buJbmggKHgsIHkpICjEkeG7gyB4IDw9IHkgY2hvIGThu4UgeMOpdCkgc+G6vSB0aOG7j2EgbcOjbiBj4bq3cCB0cnV54buBbiB0aMO0bmcgKHMsIHQpIGtoaSBj4bqjIMSR4buJbmggcyB2w6AgdCBu4bqxbSB0csOqbiDEkcaw4budbmcgxJFpIHThu6sgeC0+eQoqTmdvw6BpIHJhLCBuaOG7r25nIGPhurdwIMSR4buJbmggKHgseSkgdGjhu49hIG3Do24gKHMsIHQpIMSRw7Mgc+G6vSB04bqhbyB0aMOgbmggbeG7mXQvaGFpIHbDuW5nIGNo4buvIG5o4bqtdCBuaMawIHNhdToKKyBDYXNlIDE6IHMgdsOgIHQg4bufIDIgbmjDoW5oIGtow6FjIG5oYXUgKHMga2jDtG5nIHBo4bqjaSBsw6AgdOG7lSB0acOqbiBj4bunYSB0KQpLaGkgxJHDsyB4IG7hurFtIHRyb25nIGPDonkgY29uIGPhu6dhIHMgdsOgIHkgbuG6sW0gdHJvbmcgY8OieSBjb24gY+G7p2EgdCBz4bq9IGx1w7RuIHRo4buPYSBtw6NuCuKHkiBU4bqhbyByYSBow6xuaCBjaOG7ryBuaOG6rXQ6IFt0aW5bc10sIHRvdXRbc11dIHggW3Rpblt0XSwgdG91dFt0XV0gduG7m2kgdHLhu41uZyBz4buRIHAKWGVtIGjDrG5oIOG7nyDEkcOieSBjaG8gZOG7hSBoaeG7g3U6IGh0dHBzOi8vZi4uLmNvbnRlbnQtYXZhaWxhYmxlLXRvLWF1dGhvci1vbmx5Li4uZS5ob3N0L2kvSzBCajh6YgoKKyBDYXNlIDI6IHMgbMOgIHThu5UgdGnDqm4gY+G7p2EgdApH4buNaSB1IGzDoCDEkeG7qWEgY29uIGPhu6dhIHMgbuG6sW0gdHLDqm4gxJHGsOG7nW5nIHMgLT4gdC4gKGThu4UgZMOgbmcgdMOsbSBi4bqxbmcgYmluYXJ5IGxpZnRpbmcgdHJvbmcgTyhsb2dOKSkKTXXhu5FuIMSRxrDhu51uZyAoeCwgeSkgY2jhu6lhIGPhuqMgcyB2w6AgdCB0aMOsIG3hu5l0IMSR4bqndSBtw7p0IHBo4bqjaSDhu58gdHJvbmcgY8OieSBjb24gY+G7p2EgdCwgY8OybiDEkeG6p3Uga2lhIHBo4bqjaSBu4bqxbSBuZ2/DoGkgY8OieSBjb24gY+G7p2EgdQoodsOsIG7hur91IMSR4buBdSDhu58gdHJvbmcgdGjDrCDEkcaw4budbmcga2jDtG5nICJjaOG6oW0iIHThu5tpIHMpLgpEbyB0YSB4w6l0IGPhurdwIHgsIHkgdsOgIMSR4bq3dCB0cuG7pWMgdHVuZyB0aGVvIHkgbMOgIGPDonkgY29uIGPhu6dhIHQsIHBo4bqnbiB0aGVvIHRy4bulYyBob8OgbmggbMOgICJuZ2/DoGkgY8OieSBjb24gdSIgdMOhY2ggdGjDoG5oIGhhaSDEkW/huqFuOgoKWzEsIHRpblt1XS0xXSB2w6AgW3RvdXRbdV0rMSwgTl0K4oeSIFThuqFvIHJhIGhhaSBow6xuaCBjaOG7ryBuaOG6rXQ6IFsxLCB0aW5bdV0tMV0geCBbdGluW3RdLCB0b3V0W3RdXSwgW3RvdXRbdV0rMSxOXSB4IFt0aW5bdF0sIHRvdXRbdF1dIHbhu5tpIHRy4buNbmcgc+G7kSBwLgpYZW0gaMOsbmgg4bufIMSRw6J5IGNobyBk4buFIGhp4buDdTogaHR0cHM6Ly9mLi4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi5lLmhvc3QvaS9ncmFwaDE3NTg4NTA0ODQ3ODUuSzBCVnpNQgoKTmdvw6BpIHJhIGRvIMSRw6MgY+G7kSDEkeG7i25oIHggPD0geSwgbsOqbiBraGkgY8OgaSB0YSBjxaluZyBj4bqnbiDEkeG6o28gbOG6oWkgKGhheSBwdXNoIHRow6ptKSBj4bq3cCh5LCB4KTsKCkdp4budIMSRw6J5IGNodXnhu4NuIHNhbmcgYsOgaSB0b8OhbjoKQ2hvIGjDrG5oIHZ1w7RuZyBOIHggTjoKQ+G6rXAgbmjhuq1wIFt4MS0+eDJdIHggW3kxLT55Ml0gbMOqbiBwIGdpw6EgdOG7iwoKVMOsbSBtYXggKHgsIHkpCgpW4bubaSBzdWIgMiBOID0gMWU0ClRhIGPDsyB0aOG7gyBmaWxsIGLhurFuZyBwcmVmaXggc3VtICh0dXkgbmhpw6puIG7hur91IHbhuq15IHPhur0gdOG7kW4gYuG7mSBuaOG7myBOICogTikuCk5nb8OgaSByYSBjw7JuIGPDsyB0aOG7gyBjw6BpIHN3ZWVwbGluZSBuaMawbmcgdXBkYXRlIE8gKE4pCnRpbWUgY29tcGxleGl0eTogTyhOICogTiArIE1sb2dOICsgTmxvZ04pCgpIb+G6t2MgY8OgaSBjaGlhIGPEg246CihuK20pbgp0aW1lIGNvbXBsZXhpdHk6IE8oKE4gKyBNKeKImihOKSArIE1sb2dOICsgTmxvZ04pCgooRG8gbMaw4budaSBuw6puIGNvZGUgc+G6vSBjb2RlIGThuqFuZyBwcmVmaXggc3VtIGZpbGwgxJFv4bqhbikKKi8KCm5hbWVzcGFjZSBzdWIzIHsKaW50IHN0W04gKiA0XSwgbHpbTiAqIDRdOwpzdHJ1Y3QgRWRnZSB7CiAgICBpbnQgeDEsIHgyLCB5LCBwOwp9Owp2ZWN0b3I8RWRnZT4gRTsKdm9pZCBidWlsZChpbnQgaWQsIGludCBsLCBpbnQgcikgewoKfQp2b2lkIGRvd24oaW50IGlkKSB7Cgp9CnZvaWQgdXBkYXRlKGludCBpZCwgaW50IGwsIGludCByLCBpbnQgdSwgaW50IHYsIGludCB0KSB7Cgp9CnZvaWQgc29sdmUoKSB7CiAgICBpbml0KCk7CgogICAgY291dCA8PCBhbnMgPDwgIlxuIjsKfQp9OwoKLyoKc3ViIDM6Clbhu5tpIE4gPSAxNTAwMDAKVGEgY+G6rXAgbmjhuq1wIGLhurFuZyBEdXnhu4d0IHF1w6l0IChzd2VlcC1saW5lKSB0aGVvIHkgKyBDw6J5IMSRb+G6oW4gKHNlZ21lbnQgdHJlZSkgMUQgdHLDqm4geApN4buXaSBow6xuaCBjaOG7ryBuaOG6rXQgW1gxLCBYMl0gw5cgW1kxLCBZMl0gxJHGsOG7o2MgdMOhY2ggdGjDoG5oIGhhaSBz4buxIGtp4buHbjoKTeG7nyB04bqhaSB5ID0gWeKCgTogY+G7mW5nICtwIGNobyBraG/huqNuZyB4IOKIiCBbWDEsIFgyXS4KxJDDs25nIHThuqFpIHkgPSBZMiArIDE6IGPhu5luZyAtcCBjaG8ga2hv4bqjbmcgeCDiiIggW3gxLCBYMl0uCnNlZ3RyZWUgbGF6eSByYW5nZSBhZGQgdHLhu7FjIHRp4bq/cCB0csOqbiBt4bqjbmcgZ2nDoSB0cuG7iyBBIChBW3hdID0gdOG7lW5nIHRy4buNbmcgc+G7kSDEkWFuZyBwaOG7pyB04bqhaSBob8OgbmggxJHhu5kgeCkuCk3hu5dpIHPhu7Ega2nhu4duIFt4MSx4Ml0gbMOgIHJhbmdlIGFkZCBBW3gxLi54Ml0rPXc7IHNhdSBraGkgeOG7rSBsw70gdOG6pXQgY+G6oyBz4buxIGtp4buHbiBj4bunYSBt4buZdCB5LCBs4bqleSBtYXgoQSkKU2F1IGtoaSB44butIGzDvSBjw6FjIHPhu7Ega2nhu4duIGPhu6dhIHksIGPhuq1wIG5o4bqtdCByZXMgPSBtYXgocmVzLCB0cmVlWzFdLm1heCkuCkvhur90IGx14bqtbjogcmVzIGNow61uaCBsw6AgdOG7lW5nIGzhu6NpIG5odeG6rW4gbOG7m24gbmjhuqV0IGtoaSBjaOG7jW4gbeG7mXQgxJHGsOG7nW5nIHRyw6puIGPDonkuCnRpbWUgY29tcGxleGl0eTogTygoTiArIE0pbG9nTikKCipOZ2/DoGkgcmEgY8OzIHRo4buDIGPDoGkgQklUMkQgbmjGsG5nIGtow7RuZyBuw6puCiovCnNpZ25lZCBtYWluKCkgewogICAgY2luLnRpZShOVUxMKS0+c3luY193aXRoX3N0ZGlvKGZhbHNlKTsKICAgIGlmKGlmc3RyZWFtKCJORVRTUlYuaW5wIikpIHsKICAgICAgICBmcmVvcGVuKCJORVRTUlYuaW5wIiwgInIiLCBzdGRpbik7CiAgICAgICAgZnJlb3BlbigiTkVUU1JWLm91dCIsICJ3Iiwgc3Rkb3V0KTsKICAgIH0KICAgIGludCB0dDsgY2luID4+IHR0OwogICAgd2hpbGUodHQtLSkgewogICAgICAgIGNpbiA+PiBuOwogICAgICAgIGZvciAoaW50IGkgPSAxOyBpIDwgbjsgaSsrKSB7CiAgICAgICAgICAgIGludCB1LCB2OyBjaW4gPj4gdSA+PiB2OwogICAgICAgICAgICBHW3VdLnB1c2hfYmFjayh2KTsKICAgICAgICAgICAgR1t2XS5wdXNoX2JhY2sodSk7CiAgICAgICAgfQogICAgICAgIGNpbiA+PiBtOwogICAgICAgIGZvciAoaW50IGkgPSAxOyBpIDw9IG07IGkrKykgewogICAgICAgICAgICBjaW4gPj4gYVtpXS5zID4+IGFbaV0udCA+PiBhW2ldLnA7CiAgICAgICAgfQogICAgICAgIC8vIHN1YjM6OnNvbHZlKCk7CiAgICAgICAgaWYgKG4gPD0gMTAwKSBzdWIxOjpzb2x2ZSgpOwogICAgICAgIGVsc2UgaWYgKG4gPD0gMTAwMCkgc3ViMjo6c29sdmUoKTsKICAgICAgICBlbHNlIHN1YjM6OnNvbHZlKCk7CiAgICAgICAgCiAgICAgICAgZm9yIChpbnQgaSA9IDE7IGkgPD0gbjsgaSsrKSBHW2ldLmNsZWFyKCk7CiAgICAgICAgYW5zID0gMDsgCiAgICB9CiAgICByZXR1cm4gMDsKfQ==