#include "bits/stdc++.h"
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define ll long long
#define ld double
#define pb push_back
#define pf push_front
#define ppb pop_back
#define ff first
#define ss second
#define ins insert
#define vll vector <ll>
#define vvll vector <vll>
#define vbool vector <bool>
#define pll pair <ll,ll>
#define vpll vector <pll>
#define YY cout<<"YES"
#define NN cout<<"NO"
#define yy cout<<"Yes"
#define nn cout<<"No"
#define set_bits __builtin_popcountll
#define sz(v) (int)v.size()
#define all(v) v.begin(), v.end()
#define allr(v) v.rbegin(), v.rend()
#define desc() greater <ll>()
#define fill1(a,x) for (auto &it: a) it=x;
#define fill2(a,x) for (auto &v: a) { for (auto &it: v) it=x; }
#define endl '\n' //not to be used in interactive problems
#define random(l,r,T) uniform_int_distribution<T>(l,r)(rng)
#define fastIO ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int M = 1e9+7;
const int MM = 998244353;
const int N = 2e5+7;
const ll inf = 1e18;
const ld eps = 1e-9;
#define PI 3.141592653589793238462
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
int Dx[]={0,1,1,1,0,-1,-1,-1};
int Dy[]={1,1,0,-1,-1,-1,0,1};
// ******** Policy Based Data Structures ********
template<class T> using oset = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
template<class key, class value> using omap = tree <key,value,less<key>,rb_tree_tag,tree_order_statistics_node_update>;
// find_by_order(k) -> returns iterator to kth element from start 0
// order_of_key(k) -> returns count of elements < k
// ******** Debug Helper ********
vector<string> vec_splitter(string s) {
s += ',';
vector<string> res;
while(!s.empty()) {
res.push_back(s.substr(0, s.find(',')));
s = s.substr(s.find(',') + 1);
}
return res;
}
void debug_out(
vector<string> __attribute__ ((unused)) args,
__attribute__ ((unused)) int idx,
__attribute__ ((unused)) int LINE_NUM) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, int LINE_NUM, Head H, Tail... T) {
if(idx > 0) cerr << ", "; else cerr << "Line(" << LINE_NUM << ") ";
stringstream ss; ss << H;
cerr << args[idx] << " = " << ss.str();
debug_out(args, idx + 1, LINE_NUM, T...);
}
template<typename C,
typename T = std::decay_t<decltype(*begin(std::declval<C>()))>,
typename std::enable_if<!std::is_same<C, std::string>::value>::type* = nullptr
>
std::ostream &operator<<(std::ostream &os, const C &container)
{
bool first = true;
std::stringstream ss;
ss << '[';
for(const auto &x : container){
if (!first){
ss << ", ";
}
first = false;
ss << x;
}
ss << ']';
return os << ss.str();
}
#ifndef ONLINE_JUDGE
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __LINE__, __VA_ARGS__)
#else
#define debug(...) 42
#endif
// ******** Useful Fuctions ********
ll gcd(ll a, ll b) { while (b) {a %= b; swap(a,b);} return a; }
ll lcm(ll a, ll b) { ll g=gcd(a,b); ll res=a*(b/g); return res; }
ll extended_gcd(ll a, ll b, ll &x, ll &y) { if (b==0) { x=1; y=0; return a; } ll x1,y1; ll g=extended_gcd(b,a%b,x1,y1); x=y1; y=x1-y1*(a/b); return g; }
ll binExp(ll a, ll b, ll m=M) { a = a % m; ll res = 1; while (b) { if (b&1) { res=(res * a) % m; } a=(a * a) % m; b>>=1; } return res; }
ll mod_inv(ll a, ll m=M) { a = a % m; return binExp(a,m-2,m); } // only for prime m
ll mod_add(ll a, ll b, ll m=M) { a = a % m; b = b % m; return (((a + b) % m) + m) % m; }
ll mod_sub(ll a, ll b, ll m=M) { a = a % m; b = b % m; return (((a - b) % m) + m) % m; }
ll mod_mul(ll a, ll b, ll m=M) { a = a % m; b = b % m; return (((a * b) % m) + m) % m; }
ll mod_div(ll a, ll b, ll m=M) { a = a % m; ll binv = mod_inv(b,m); return (((a * binv) % m) + m) % m; }
ll sqrtll(ll n) { ll lo=0,hi=3037000499; while (hi-lo>1) { ll m=(hi+lo)/2; if (m*m<=n) { lo=m; } else { hi=m-1; }} if (hi*hi<=n) { return hi; } return lo; }
ld sqrtld(ll n) { ld lo=0,hi=3037000499; while (hi-lo>eps) { ld m=(hi+lo)/2; if ((n-m*m)>eps) { lo=m; } else { hi=m-eps; }} return lo; }
ll cbrtll(ll n) { ll lo=0,hi=2097151; while (hi-lo>1) { ll m=(hi+lo)/2; if (m*m*m<=n) { lo=m; } else { hi=m-1; }} if (hi*hi*hi<=n) { return hi; } return lo; }
ld cbrtld(ll n) { ld lo=0,hi=2097151; while (hi-lo>eps) { ld m=(hi+lo)/2; if ((n-m*m*m)>eps) { lo=m; } else { hi=m-eps; }} return lo; }
void init_usaco() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); }
// ******** Input/Output Template *********
template<typename T> istream& operator >>(istream &in,vector<T> &v){ for(auto &x:v) in>>x; return in;}
template<typename T> ostream& operator <<(ostream &out,const vector<T> &v){ for(auto &x:v) out<<x<<' '; return out;}
template<typename T1,typename T2> istream& operator >>(istream &in,pair<T1,T2> &p){ in>>p.first>>p.second; return in;}
template<typename T1,typename T2> ostream& operator <<(ostream &out,const pair<T1,T2> &p){ out<<p.first<<' '<<p.second; return out;}
// ******** ACCEPTED ********
vll color,val;
vll parent,sbtreeSize,lvl,chain,chainHead,positionInHldArr;
vll hldArr,hldValArr;
vll inTime,outTime;
vvll up;
ll pos,chainId;
typedef struct Node
{
ll w=0,b=0,sumW=0,sumB=0;
}Node;
vector <Node> arr; // { sum of white, sum of black}
vll lazyarr; // { 0 -> no update, 1-> update to black node 2-> update to white node}
void dfs(ll node, ll par, ll l, vll adj[])
{
sbtreeSize[node]=1;
parent[node]=par;
up[node][0]=par;
lvl[node]=l;
// binary lifting
for (ll i=1;i<20;i++)
{
if (up[node][i-1]!=-1)
up[node][i]=up[up[node][i-1]][i-1];
else
up[node][i]=-1;
}
for (auto &it: adj[node])
{
if (it!=par)
{
dfs(it,node,l+1,adj);
sbtreeSize[node]+=sbtreeSize[it];
}
}
}
ll lift_node(ll node, ll k)
{
for (ll i=19;i>=0 && node!=-1;i--)
{
if (k&(1LL<<i))
node=up[node][i];
}
return node;
}
ll LCA(ll a, ll b)
{
if (lvl[a]<lvl[b]) swap(a,b);
a=lift_node(a,lvl[a]-lvl[b]);
if (a==b) return a;
for (ll i=19;i>=0;i--)
{
ll para=up[a][i];
ll parb=up[b][i];
if (para!=parb)
{
a=para;
b=parb;
}
}
return lift_node(a,1);
}
void HLD(ll node, ll par, vll adj[])
{
chain[node]=chainId;
hldArr[pos]=node;
hldValArr[pos]=val[node];
positionInHldArr[node]=pos;
inTime[node]=pos++;
ll heavyChild=-1,heavySize=0;
for (auto &it: adj[node])
{
if (it!=par)
{
if (sbtreeSize[it]>heavySize)
{
heavySize=sbtreeSize[it];
heavyChild=it;
}
}
}
if (heavySize>0) HLD(heavyChild,node,adj); // not leaf, move to heavy edge
for (auto &it: adj[node])
{
if (it!=par && it!=heavyChild)
{
chainHead[++chainId]=it;
HLD(it,node,adj);
}
}
outTime[node]=pos-1;
}
void merge(ll ind, ll left, ll right)
{
arr[ind].w=arr[left].w+arr[right].w;
arr[ind].b=arr[left].b+arr[right].b;
arr[ind].sumW=arr[left].sumW+arr[right].sumW;
arr[ind].sumB=arr[left].sumB+arr[right].sumB;
}
void update_lazy(ll ind, ll lo, ll hi)
{
if (lazyarr[ind]==0) return;
ll upd=lazyarr[ind];
lazyarr[ind]=0;
if (upd==1)
{
arr[ind].w+=arr[ind].b;
arr[ind].sumW+=arr[ind].sumB;
arr[ind].b=arr[ind].sumB=0;
}
else
{
arr[ind].b+=arr[ind].w;
arr[ind].sumB+=arr[ind].sumW;
arr[ind].w=arr[ind].sumW=0;
}
if (lo!=hi) lazyarr[2*ind+1]=upd, lazyarr[2*ind+2]=upd;
}
void buildSegTree(ll ind, ll lo, ll hi)
{
if (lo==hi)
{
arr[ind].w=1;
arr[ind].sumW=hldValArr[lo];
arr[ind].b=arr[ind].sumB=0;
return;
}
ll mid=(hi+lo)/2;
buildSegTree(2*ind+1,lo,mid);
buildSegTree(2*ind+2,mid+1,hi);
merge(ind,2*ind+1,2*ind+2);
}
/*Query:
1 -> get white count
2 -> get black count
3 -> get sum white
4 -> get sum black*/
ll querySegTree(ll ind, ll lo, ll hi, ll l, ll r, ll d)
{
// check for update
update_lazy(ind,lo,hi);
if (lo>r || hi<l) return 0;
else if (lo>=l && hi<=r)
{
if (d==1) return arr[ind].w;
else if (d==2) return arr[ind].b;
else if (d==3) return arr[ind].sumW;
else return arr[ind].sumB;
}
ll mid=(hi+lo)/2;
ll left=querySegTree(2*ind+1,lo,mid,l,r,d);
ll right=querySegTree(2*ind+2,mid+1,hi,l,r,d);
ll ans=left+right;
return ans;
}
/*Update:
1 -> force all white
2 -> force all black*/
void updateSegTree(ll ind, ll lo, ll hi, ll l, ll r, ll x)
{
// check for update
update_lazy(ind,lo,hi);
if (lo>r || hi<l) return;
else if (lo>=l && hi<=r)
{
if (x==1)
{
arr[ind].w+=arr[ind].b;
arr[ind].sumW+=arr[ind].sumB;
arr[ind].b=arr[ind].sumB=0;
}
else
{
arr[ind].b+=arr[ind].w;
arr[ind].sumB+=arr[ind].sumW;
arr[ind].w=arr[ind].sumW=0;
}
if (lo!=hi) lazyarr[2*ind+1]=x, lazyarr[2*ind+2]=x;
return;
}
ll mid=(hi+lo)/2;
updateSegTree(2*ind+1,lo,mid,l,r,x);
updateSegTree(2*ind+2,mid+1,hi,l,r,x);
merge(ind,2*ind+1,2*ind+2);
}
void hld_query1()
{
ll n=sz(hldArr);
ll x,y; cin>>x>>y; x--; y--;
ll lca=LCA(x,y);
ll whiteCnt=0,blackCnt=0;
ll a=x,b=y;
while (chain[a]!=chain[lca])
{
whiteCnt+=querySegTree(0,0,n-1,positionInHldArr[chainHead[chain[a]]],positionInHldArr[a],1);
blackCnt+=querySegTree(0,0,n-1,positionInHldArr[chainHead[chain[a]]],positionInHldArr[a],2);
a=up[chainHead[chain[a]]][0];
}
whiteCnt+=querySegTree(0,0,n-1,positionInHldArr[lca],positionInHldArr[a],1);
blackCnt+=querySegTree(0,0,n-1,positionInHldArr[lca],positionInHldArr[a],2);
while (chain[b]!=chain[lca])
{
whiteCnt+=querySegTree(0,0,n-1,positionInHldArr[chainHead[chain[b]]],positionInHldArr[b],1);
blackCnt+=querySegTree(0,0,n-1,positionInHldArr[chainHead[chain[b]]],positionInHldArr[b],2);
b=up[chainHead[chain[b]]][0];
}
whiteCnt+=querySegTree(0,0,n-1,positionInHldArr[lca],positionInHldArr[b],1);
blackCnt+=querySegTree(0,0,n-1,positionInHldArr[lca],positionInHldArr[b],2);
if (querySegTree(0,0,n-1,positionInHldArr[lca],positionInHldArr[lca],1)==1) whiteCnt--;
else blackCnt--;
if (whiteCnt>blackCnt)
{
// force white in path
a=x,b=y;
while (chain[a]!=chain[lca])
{
updateSegTree(0,0,n-1,positionInHldArr[chainHead[chain[a]]],positionInHldArr[a],1);
a=up[chainHead[chain[a]]][0];
}
updateSegTree(0,0,n-1,positionInHldArr[lca],positionInHldArr[a],1);
while (chain[b]!=chain[lca])
{
updateSegTree(0,0,n-1,positionInHldArr[chainHead[chain[b]]],positionInHldArr[b],1);
b=up[chainHead[chain[b]]][0];
}
updateSegTree(0,0,n-1,positionInHldArr[lca],positionInHldArr[b],1);
}
else if (blackCnt>whiteCnt)
{
// force black in path
a=x,b=y;
while (chain[a]!=chain[lca])
{
updateSegTree(0,0,n-1,positionInHldArr[chainHead[chain[a]]],positionInHldArr[a],2);
a=up[chainHead[chain[a]]][0];
}
updateSegTree(0,0,n-1,positionInHldArr[lca],positionInHldArr[a],2);
while (chain[b]!=chain[lca])
{
updateSegTree(0,0,n-1,positionInHldArr[chainHead[chain[b]]],positionInHldArr[b],2);
b=up[chainHead[chain[b]]][0];
}
updateSegTree(0,0,n-1,positionInHldArr[lca],positionInHldArr[b],2);
}
}
void hld_query2()
{
ll n=sz(hldArr);
ll x; cin>>x; x--;
// color subtree x with black
updateSegTree(0,0,n-1,inTime[x],outTime[x],2);
}
ll hld_query3()
{
ll n=sz(hldArr);
ll x,y; cin>>x>>y; x--; y--;
ll lca=LCA(x,y);
ll whiteSum=0,blackSum=0;
ll a=x,b=y;
while (chain[a]!=chain[lca])
{
whiteSum+=querySegTree(0,0,n-1,positionInHldArr[chainHead[chain[a]]],positionInHldArr[a],3);
blackSum+=querySegTree(0,0,n-1,positionInHldArr[chainHead[chain[a]]],positionInHldArr[a],4);
a=up[chainHead[chain[a]]][0];
}
whiteSum+=querySegTree(0,0,n-1,positionInHldArr[lca],positionInHldArr[a],3);
blackSum+=querySegTree(0,0,n-1,positionInHldArr[lca],positionInHldArr[a],4);
while (chain[b]!=chain[lca])
{
whiteSum+=querySegTree(0,0,n-1,positionInHldArr[chainHead[chain[b]]],positionInHldArr[b],3);
blackSum+=querySegTree(0,0,n-1,positionInHldArr[chainHead[chain[b]]],positionInHldArr[b],4);
b=up[chainHead[chain[b]]][0];
}
whiteSum+=querySegTree(0,0,n-1,positionInHldArr[lca],positionInHldArr[b],3);
blackSum+=querySegTree(0,0,n-1,positionInHldArr[lca],positionInHldArr[b],4);
if (querySegTree(0,0,n-1,positionInHldArr[lca],positionInHldArr[lca],1)==1) whiteSum-=val[lca];
else blackSum-=val[lca];
return max(whiteSum,blackSum);
}
void solve()
{
ll n,m; cin>>n>>m;
hldArr.resize(n);
hldValArr.resize(n);
vll adj[n];
for (ll i=0;i<n-1;i++)
{
ll u,v; cin>>u>>v; u--; v--;
adj[u].push_back(v);
adj[v].push_back(u);
}
val.resize(n); cin>>val;
color.resize(n,0);
parent.resize(n);
sbtreeSize.resize(n);
lvl.resize(n);
chain.resize(n);
chainHead.resize(n);
positionInHldArr.resize(n);
inTime.resize(n);
outTime.resize(n);
up.resize(n, vll (20,-1));
arr.resize(4*n);
lazyarr.resize(4*n,0);
dfs(0,-1,0,adj);
pos=chainId=0;
HLD(0,-1,adj);
debug(hldArr);
debug(hldValArr);
debug(inTime);
debug(outTime);
buildSegTree(0,0,n-1);
while (m--)
{
ll q; cin>>q;
if (q==1) hld_query1();
else if (q==2) hld_query2();
else cout<<hld_query3()<<endl;
}
}
int main()
{
#ifndef ONLINE_JUDGE
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
freopen("error.txt","w",stderr);
clock_t clk = clock();
#endif
// init_usaco();
fastIO;
int t=1;
// cin>>t;
for (int test=1;test<=t;test++)
{
// cout<<"Case #"<<test<<": ";
solve();
cout<<endl;
}
#ifndef ONLINE_JUDGE
cerr << '\n'<<"Time (in s): " << double(clock() - clk) * 1.0 / CLOCKS_PER_SEC << '\n';
#endif
return 0;
}
I2luY2x1ZGUgImJpdHMvc3RkYysrLmgiCiNpbmNsdWRlIDxleHQvcGJfZHMvYXNzb2NfY29udGFpbmVyLmhwcD4KI2luY2x1ZGUgPGV4dC9wYl9kcy90cmVlX3BvbGljeS5ocHA+Cgp1c2luZyBuYW1lc3BhY2Ugc3RkOwp1c2luZyBuYW1lc3BhY2UgX19nbnVfcGJkczsKCiNkZWZpbmUgbGwgbG9uZyBsb25nCiNkZWZpbmUgbGQgZG91YmxlCiNkZWZpbmUgcGIgcHVzaF9iYWNrCiNkZWZpbmUgcGYgcHVzaF9mcm9udAojZGVmaW5lIHBwYiBwb3BfYmFjawojZGVmaW5lIGZmIGZpcnN0CiNkZWZpbmUgc3Mgc2Vjb25kCiNkZWZpbmUgaW5zIGluc2VydAojZGVmaW5lIHZsbCB2ZWN0b3IgPGxsPgojZGVmaW5lIHZ2bGwgdmVjdG9yIDx2bGw+CiNkZWZpbmUgdmJvb2wgdmVjdG9yIDxib29sPgojZGVmaW5lIHBsbCBwYWlyIDxsbCxsbD4KI2RlZmluZSB2cGxsIHZlY3RvciA8cGxsPgojZGVmaW5lIFlZIGNvdXQ8PCJZRVMiCiNkZWZpbmUgTk4gY291dDw8Ik5PIgojZGVmaW5lIHl5IGNvdXQ8PCJZZXMiCiNkZWZpbmUgbm4gY291dDw8Ik5vIgojZGVmaW5lIHNldF9iaXRzIF9fYnVpbHRpbl9wb3Bjb3VudGxsCiNkZWZpbmUgc3oodikgKGludCl2LnNpemUoKQojZGVmaW5lIGFsbCh2KSB2LmJlZ2luKCksIHYuZW5kKCkKI2RlZmluZSBhbGxyKHYpIHYucmJlZ2luKCksIHYucmVuZCgpCiNkZWZpbmUgZGVzYygpIGdyZWF0ZXIgPGxsPigpCiNkZWZpbmUgZmlsbDEoYSx4KSBmb3IgKGF1dG8gJml0OiBhKSBpdD14OwojZGVmaW5lIGZpbGwyKGEseCkgZm9yIChhdXRvICZ2OiBhKSB7IGZvciAoYXV0byAmaXQ6IHYpIGl0PXg7IH0KI2RlZmluZSBlbmRsICdcbicgICAvL25vdCB0byBiZSB1c2VkIGluIGludGVyYWN0aXZlIHByb2JsZW1zCiNkZWZpbmUgcmFuZG9tKGwscixUKSB1bmlmb3JtX2ludF9kaXN0cmlidXRpb248VD4obCxyKShybmcpCiNkZWZpbmUgZmFzdElPIGlvc19iYXNlOjpzeW5jX3dpdGhfc3RkaW8oZmFsc2UpOyBjaW4udGllKE5VTEwpOyBjb3V0LnRpZShOVUxMKTsKCm10MTk5Mzcgcm5nKGNocm9ubzo6c3RlYWR5X2Nsb2NrOjpub3coKS50aW1lX3NpbmNlX2Vwb2NoKCkuY291bnQoKSk7Cgpjb25zdCBpbnQgTSA9IDFlOSs3Owpjb25zdCBpbnQgTU0gPSA5OTgyNDQzNTM7CmNvbnN0IGludCBOID0gMmU1Kzc7CmNvbnN0IGxsIGluZiA9IDFlMTg7CmNvbnN0IGxkIGVwcyA9IDFlLTk7CiNkZWZpbmUgUEkgMy4xNDE1OTI2NTM1ODk3OTMyMzg0NjIKCmludCBkeFtdPXswLDEsMCwtMX07CmludCBkeVtdPXsxLDAsLTEsMH07CmludCBEeFtdPXswLDEsMSwxLDAsLTEsLTEsLTF9OwppbnQgRHlbXT17MSwxLDAsLTEsLTEsLTEsMCwxfTsKCgovLyAqKioqKioqKiAgICAgUG9saWN5IEJhc2VkIERhdGEgU3RydWN0dXJlcyAgICAgKioqKioqKioKdGVtcGxhdGU8Y2xhc3MgVD4gdXNpbmcgb3NldCA9IHRyZWU8VCxudWxsX3R5cGUsbGVzczxUPixyYl90cmVlX3RhZyx0cmVlX29yZGVyX3N0YXRpc3RpY3Nfbm9kZV91cGRhdGU+Owp0ZW1wbGF0ZTxjbGFzcyBrZXksIGNsYXNzIHZhbHVlPiB1c2luZyBvbWFwID0gdHJlZSA8a2V5LHZhbHVlLGxlc3M8a2V5PixyYl90cmVlX3RhZyx0cmVlX29yZGVyX3N0YXRpc3RpY3Nfbm9kZV91cGRhdGU+OwovLyBmaW5kX2J5X29yZGVyKGspIC0+IHJldHVybnMgaXRlcmF0b3IgdG8ga3RoIGVsZW1lbnQgZnJvbSBzdGFydCAwCi8vIG9yZGVyX29mX2tleShrKSAtPiByZXR1cm5zIGNvdW50IG9mIGVsZW1lbnRzIDwgawoKCi8vICoqKioqKioqICAgICBEZWJ1ZyBIZWxwZXIgICAgICoqKioqKioqCnZlY3RvcjxzdHJpbmc+IHZlY19zcGxpdHRlcihzdHJpbmcgcykgewogICAgcyArPSAnLCc7CiAgICB2ZWN0b3I8c3RyaW5nPiByZXM7CiAgICB3aGlsZSghcy5lbXB0eSgpKSB7CiAgICAgICAgcmVzLnB1c2hfYmFjayhzLnN1YnN0cigwLCBzLmZpbmQoJywnKSkpOwogICAgICAgIHMgPSBzLnN1YnN0cihzLmZpbmQoJywnKSArIDEpOwogICAgfQogICAgcmV0dXJuIHJlczsKfQoKdm9pZCBkZWJ1Z19vdXQoCnZlY3RvcjxzdHJpbmc+IF9fYXR0cmlidXRlX18gKCh1bnVzZWQpKSBhcmdzLApfX2F0dHJpYnV0ZV9fICgodW51c2VkKSkgaW50IGlkeCwgCl9fYXR0cmlidXRlX18gKCh1bnVzZWQpKSBpbnQgTElORV9OVU0pIHsgY2VyciA8PCBlbmRsOyB9IAp0ZW1wbGF0ZSA8dHlwZW5hbWUgSGVhZCwgdHlwZW5hbWUuLi4gVGFpbD4Kdm9pZCBkZWJ1Z19vdXQodmVjdG9yPHN0cmluZz4gYXJncywgaW50IGlkeCwgaW50IExJTkVfTlVNLCBIZWFkIEgsIFRhaWwuLi4gVCkgewogICAgaWYoaWR4ID4gMCkgY2VyciA8PCAiLCAiOyBlbHNlIGNlcnIgPDwgIkxpbmUoIiA8PCBMSU5FX05VTSA8PCAiKSAiOwogICAgc3RyaW5nc3RyZWFtIHNzOyBzcyA8PCBIOwogICAgY2VyciA8PCBhcmdzW2lkeF0gPDwgIiA9ICIgPDwgc3Muc3RyKCk7CiAgICBkZWJ1Z19vdXQoYXJncywgaWR4ICsgMSwgTElORV9OVU0sIFQuLi4pOwp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBDLCAKICAgICAgICAgdHlwZW5hbWUgVCA9IHN0ZDo6ZGVjYXlfdDxkZWNsdHlwZSgqYmVnaW4oc3RkOjpkZWNsdmFsPEM+KCkpKT4sCiAgICAgICAgIHR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPCFzdGQ6OmlzX3NhbWU8Qywgc3RkOjpzdHJpbmc+Ojp2YWx1ZT46OnR5cGUqID0gbnVsbHB0cgogICAgICAgICA+CnN0ZDo6b3N0cmVhbSAmb3BlcmF0b3I8PChzdGQ6Om9zdHJlYW0gJm9zLCBjb25zdCBDICZjb250YWluZXIpCnsKICBib29sIGZpcnN0ID0gdHJ1ZTsKICBzdGQ6OnN0cmluZ3N0cmVhbSBzczsgCiAgc3MgPDwgJ1snOwogIGZvcihjb25zdCBhdXRvICZ4IDogY29udGFpbmVyKXsKICAgIGlmICghZmlyc3QpewogICAgICBzcyA8PCAiLCAiOwogICAgfQogICAgZmlyc3QgPSBmYWxzZTsKICAgIHNzIDw8IHg7CiAgfQogIHNzIDw8ICddJzsKICByZXR1cm4gb3MgPDwgc3Muc3RyKCk7Cn0KCiNpZm5kZWYgT05MSU5FX0pVREdFCiAgICAjZGVmaW5lIGRlYnVnKC4uLikgZGVidWdfb3V0KHZlY19zcGxpdHRlcigjX19WQV9BUkdTX18pLCAwLCBfX0xJTkVfXywgX19WQV9BUkdTX18pCiNlbHNlCiAgICAjZGVmaW5lIGRlYnVnKC4uLikgNDIKI2VuZGlmCgoKLy8gKioqKioqKiogICAgIFVzZWZ1bCBGdWN0aW9ucyAgICAgKioqKioqKioKbGwgZ2NkKGxsIGEsIGxsIGIpIHsgd2hpbGUgKGIpIHthICU9IGI7IHN3YXAoYSxiKTt9IHJldHVybiBhOyB9CmxsIGxjbShsbCBhLCBsbCBiKSB7IGxsIGc9Z2NkKGEsYik7IGxsIHJlcz1hKihiL2cpOyByZXR1cm4gcmVzOyB9CmxsIGV4dGVuZGVkX2djZChsbCBhLCBsbCBiLCBsbCAmeCwgbGwgJnkpIHsgaWYgKGI9PTApIHsgeD0xOyB5PTA7IHJldHVybiBhOyB9IGxsIHgxLHkxOyBsbCBnPWV4dGVuZGVkX2djZChiLGElYix4MSx5MSk7IHg9eTE7IHk9eDEteTEqKGEvYik7IHJldHVybiBnOyB9CmxsIGJpbkV4cChsbCBhLCBsbCBiLCBsbCBtPU0pIHsgYSA9IGEgJSBtOyBsbCByZXMgPSAxOyB3aGlsZSAoYikgeyBpZiAoYiYxKSB7IHJlcz0ocmVzICogYSkgJSBtOyB9IGE9KGEgKiBhKSAlIG07IGI+Pj0xOyB9IHJldHVybiByZXM7IH0KbGwgbW9kX2ludihsbCBhLCBsbCBtPU0pIHsgYSA9IGEgJSBtOyByZXR1cm4gYmluRXhwKGEsbS0yLG0pOyB9ICAgICAgICAvLyBvbmx5IGZvciBwcmltZSBtCmxsIG1vZF9hZGQobGwgYSwgbGwgYiwgbGwgbT1NKSB7IGEgPSBhICUgbTsgYiA9IGIgJSBtOyByZXR1cm4gKCgoYSArIGIpICUgbSkgKyBtKSAlIG07IH0KbGwgbW9kX3N1YihsbCBhLCBsbCBiLCBsbCBtPU0pIHsgYSA9IGEgJSBtOyBiID0gYiAlIG07IHJldHVybiAoKChhIC0gYikgJSBtKSArIG0pICUgbTsgfQpsbCBtb2RfbXVsKGxsIGEsIGxsIGIsIGxsIG09TSkgeyBhID0gYSAlIG07IGIgPSBiICUgbTsgcmV0dXJuICgoKGEgKiBiKSAlIG0pICsgbSkgJSBtOyB9CmxsIG1vZF9kaXYobGwgYSwgbGwgYiwgbGwgbT1NKSB7IGEgPSBhICUgbTsgbGwgYmludiA9IG1vZF9pbnYoYixtKTsgcmV0dXJuICgoKGEgKiBiaW52KSAlIG0pICsgbSkgJSBtOyB9CmxsIHNxcnRsbChsbCBuKSB7IGxsIGxvPTAsaGk9MzAzNzAwMDQ5OTsgd2hpbGUgKGhpLWxvPjEpIHsgbGwgbT0oaGkrbG8pLzI7IGlmIChtKm08PW4pIHsgbG89bTsgfSBlbHNlIHsgaGk9bS0xOyB9fSBpZiAoaGkqaGk8PW4pIHsgcmV0dXJuIGhpOyB9IHJldHVybiBsbzsgfQpsZCBzcXJ0bGQobGwgbikgeyBsZCBsbz0wLGhpPTMwMzcwMDA0OTk7IHdoaWxlIChoaS1sbz5lcHMpIHsgbGQgbT0oaGkrbG8pLzI7IGlmICgobi1tKm0pPmVwcykgeyBsbz1tOyB9IGVsc2UgeyBoaT1tLWVwczsgfX0gcmV0dXJuIGxvOyB9CmxsIGNicnRsbChsbCBuKSB7IGxsIGxvPTAsaGk9MjA5NzE1MTsgd2hpbGUgKGhpLWxvPjEpIHsgbGwgbT0oaGkrbG8pLzI7IGlmIChtKm0qbTw9bikgeyBsbz1tOyB9IGVsc2UgeyBoaT1tLTE7IH19IGlmIChoaSpoaSpoaTw9bikgeyByZXR1cm4gaGk7IH0gcmV0dXJuIGxvOyB9CmxkIGNicnRsZChsbCBuKSB7IGxkIGxvPTAsaGk9MjA5NzE1MTsgd2hpbGUgKGhpLWxvPmVwcykgeyBsZCBtPShoaStsbykvMjsgaWYgKChuLW0qbSptKT5lcHMpIHsgbG89bTsgfSBlbHNlIHsgaGk9bS1lcHM7IH19IHJldHVybiBsbzsgfQp2b2lkIGluaXRfdXNhY28oKSB7IGZyZW9wZW4oImlucHV0LnR4dCIsInIiLHN0ZGluKTsgZnJlb3Blbigib3V0cHV0LnR4dCIsInciLHN0ZG91dCk7IH0KCgovLyAqKioqKioqKiAgICAgSW5wdXQvT3V0cHV0IFRlbXBsYXRlICAgICAqKioqKioqKioKdGVtcGxhdGU8dHlwZW5hbWUgVD4gaXN0cmVhbSYgb3BlcmF0b3IgPj4oaXN0cmVhbSAmaW4sdmVjdG9yPFQ+ICZ2KXsgZm9yKGF1dG8gJng6dikgaW4+Png7IHJldHVybiBpbjt9CnRlbXBsYXRlPHR5cGVuYW1lIFQ+IG9zdHJlYW0mIG9wZXJhdG9yIDw8KG9zdHJlYW0gJm91dCxjb25zdCB2ZWN0b3I8VD4gJnYpeyBmb3IoYXV0byAmeDp2KSBvdXQ8PHg8PCcgJzsgcmV0dXJuIG91dDt9CnRlbXBsYXRlPHR5cGVuYW1lIFQxLHR5cGVuYW1lIFQyPiBpc3RyZWFtJiBvcGVyYXRvciA+Pihpc3RyZWFtICZpbixwYWlyPFQxLFQyPiAmcCl7IGluPj5wLmZpcnN0Pj5wLnNlY29uZDsgcmV0dXJuIGluO30KdGVtcGxhdGU8dHlwZW5hbWUgVDEsdHlwZW5hbWUgVDI+IG9zdHJlYW0mIG9wZXJhdG9yIDw8KG9zdHJlYW0gJm91dCxjb25zdCBwYWlyPFQxLFQyPiAmcCl7IG91dDw8cC5maXJzdDw8JyAnPDxwLnNlY29uZDsgcmV0dXJuIG91dDt9CgoKLy8gKioqKioqKiogICAgIEFDQ0VQVEVEICAgICAqKioqKioqKgp2bGwgY29sb3IsdmFsOwp2bGwgcGFyZW50LHNidHJlZVNpemUsbHZsLGNoYWluLGNoYWluSGVhZCxwb3NpdGlvbkluSGxkQXJyOwp2bGwgaGxkQXJyLGhsZFZhbEFycjsKdmxsIGluVGltZSxvdXRUaW1lOwp2dmxsIHVwOwpsbCBwb3MsY2hhaW5JZDsKCnR5cGVkZWYgc3RydWN0IE5vZGUKewogICAgbGwgdz0wLGI9MCxzdW1XPTAsc3VtQj0wOwp9Tm9kZTsKCnZlY3RvciA8Tm9kZT4gYXJyOyAgICAgICAgICAgICAgIC8vIHsgc3VtIG9mIHdoaXRlLCBzdW0gb2YgYmxhY2t9CnZsbCBsYXp5YXJyOyAgICAgICAgICAgIC8vIHsgMCAtPiBubyB1cGRhdGUsIDEtPiB1cGRhdGUgdG8gYmxhY2sgbm9kZSAyLT4gdXBkYXRlIHRvIHdoaXRlIG5vZGV9Cgp2b2lkIGRmcyhsbCBub2RlLCBsbCBwYXIsIGxsIGwsIHZsbCBhZGpbXSkKewogICAgc2J0cmVlU2l6ZVtub2RlXT0xOwogICAgcGFyZW50W25vZGVdPXBhcjsKICAgIHVwW25vZGVdWzBdPXBhcjsKICAgIGx2bFtub2RlXT1sOwogICAgLy8gYmluYXJ5IGxpZnRpbmcKICAgIGZvciAobGwgaT0xO2k8MjA7aSsrKQogICAgewogICAgICAgIGlmICh1cFtub2RlXVtpLTFdIT0tMSkKICAgICAgICAgICAgdXBbbm9kZV1baV09dXBbdXBbbm9kZV1baS0xXV1baS0xXTsKICAgICAgICBlbHNlCiAgICAgICAgICAgIHVwW25vZGVdW2ldPS0xOwogICAgfQogICAgZm9yIChhdXRvICZpdDogYWRqW25vZGVdKQogICAgewogICAgICAgIGlmIChpdCE9cGFyKQogICAgICAgIHsKICAgICAgICAgICAgZGZzKGl0LG5vZGUsbCsxLGFkaik7CiAgICAgICAgICAgIHNidHJlZVNpemVbbm9kZV0rPXNidHJlZVNpemVbaXRdOwogICAgICAgIH0KICAgIH0KfQoKbGwgbGlmdF9ub2RlKGxsIG5vZGUsIGxsIGspCnsKICAgIGZvciAobGwgaT0xOTtpPj0wICYmIG5vZGUhPS0xO2ktLSkKICAgIHsKICAgICAgICBpZiAoayYoMUxMPDxpKSkKICAgICAgICAgICAgbm9kZT11cFtub2RlXVtpXTsKICAgIH0KICAgIHJldHVybiBub2RlOwp9CiAKbGwgTENBKGxsIGEsIGxsIGIpCnsKICAgIGlmIChsdmxbYV08bHZsW2JdKSBzd2FwKGEsYik7CiAgICBhPWxpZnRfbm9kZShhLGx2bFthXS1sdmxbYl0pOwogICAgaWYgKGE9PWIpIHJldHVybiBhOwogICAgZm9yIChsbCBpPTE5O2k+PTA7aS0tKQogICAgewogICAgICAgIGxsIHBhcmE9dXBbYV1baV07CiAgICAgICAgbGwgcGFyYj11cFtiXVtpXTsKICAgICAgICBpZiAocGFyYSE9cGFyYikKICAgICAgICB7CiAgICAgICAgICAgIGE9cGFyYTsKICAgICAgICAgICAgYj1wYXJiOwogICAgICAgIH0KICAgIH0KICAgIHJldHVybiBsaWZ0X25vZGUoYSwxKTsKfQoKdm9pZCBITEQobGwgbm9kZSwgbGwgcGFyLCB2bGwgYWRqW10pCnsKICAgIGNoYWluW25vZGVdPWNoYWluSWQ7CiAgICBobGRBcnJbcG9zXT1ub2RlOwogICAgaGxkVmFsQXJyW3Bvc109dmFsW25vZGVdOwogICAgcG9zaXRpb25JbkhsZEFycltub2RlXT1wb3M7CiAgICBpblRpbWVbbm9kZV09cG9zKys7CiAgICBsbCBoZWF2eUNoaWxkPS0xLGhlYXZ5U2l6ZT0wOwogICAgZm9yIChhdXRvICZpdDogYWRqW25vZGVdKQogICAgewogICAgICAgIGlmIChpdCE9cGFyKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKHNidHJlZVNpemVbaXRdPmhlYXZ5U2l6ZSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgaGVhdnlTaXplPXNidHJlZVNpemVbaXRdOwogICAgICAgICAgICAgICAgaGVhdnlDaGlsZD1pdDsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIGlmIChoZWF2eVNpemU+MCkgSExEKGhlYXZ5Q2hpbGQsbm9kZSxhZGopOyAgLy8gbm90IGxlYWYsIG1vdmUgdG8gaGVhdnkgZWRnZQogICAgZm9yIChhdXRvICZpdDogYWRqW25vZGVdKQogICAgewogICAgICAgIGlmIChpdCE9cGFyICYmIGl0IT1oZWF2eUNoaWxkKQogICAgICAgIHsKICAgICAgICAgICAgY2hhaW5IZWFkWysrY2hhaW5JZF09aXQ7CiAgICAgICAgICAgIEhMRChpdCxub2RlLGFkaik7CiAgICAgICAgfQogICAgfQogICAgb3V0VGltZVtub2RlXT1wb3MtMTsKfQoKdm9pZCBtZXJnZShsbCBpbmQsIGxsIGxlZnQsIGxsIHJpZ2h0KQp7CiAgICBhcnJbaW5kXS53PWFycltsZWZ0XS53K2FycltyaWdodF0udzsKICAgIGFycltpbmRdLmI9YXJyW2xlZnRdLmIrYXJyW3JpZ2h0XS5iOwogICAgYXJyW2luZF0uc3VtVz1hcnJbbGVmdF0uc3VtVythcnJbcmlnaHRdLnN1bVc7CiAgICBhcnJbaW5kXS5zdW1CPWFycltsZWZ0XS5zdW1CK2FycltyaWdodF0uc3VtQjsKfQoKdm9pZCB1cGRhdGVfbGF6eShsbCBpbmQsIGxsIGxvLCBsbCBoaSkKewogICAgaWYgKGxhenlhcnJbaW5kXT09MCkgcmV0dXJuOwogICAgbGwgdXBkPWxhenlhcnJbaW5kXTsKICAgIGxhenlhcnJbaW5kXT0wOwogICAgaWYgKHVwZD09MSkKICAgIHsKICAgICAgICBhcnJbaW5kXS53Kz1hcnJbaW5kXS5iOwogICAgICAgIGFycltpbmRdLnN1bVcrPWFycltpbmRdLnN1bUI7CiAgICAgICAgYXJyW2luZF0uYj1hcnJbaW5kXS5zdW1CPTA7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgYXJyW2luZF0uYis9YXJyW2luZF0udzsKICAgICAgICBhcnJbaW5kXS5zdW1CKz1hcnJbaW5kXS5zdW1XOwogICAgICAgIGFycltpbmRdLnc9YXJyW2luZF0uc3VtVz0wOwogICAgfQogICAgaWYgKGxvIT1oaSkgbGF6eWFyclsyKmluZCsxXT11cGQsIGxhenlhcnJbMippbmQrMl09dXBkOwp9Cgp2b2lkIGJ1aWxkU2VnVHJlZShsbCBpbmQsIGxsIGxvLCBsbCBoaSkKewogICAgaWYgKGxvPT1oaSkKICAgIHsKICAgICAgICBhcnJbaW5kXS53PTE7CiAgICAgICAgYXJyW2luZF0uc3VtVz1obGRWYWxBcnJbbG9dOwogICAgICAgIGFycltpbmRdLmI9YXJyW2luZF0uc3VtQj0wOwogICAgICAgIHJldHVybjsKICAgIH0KICAgIGxsIG1pZD0oaGkrbG8pLzI7CiAgICBidWlsZFNlZ1RyZWUoMippbmQrMSxsbyxtaWQpOwogICAgYnVpbGRTZWdUcmVlKDIqaW5kKzIsbWlkKzEsaGkpOwogICAgbWVyZ2UoaW5kLDIqaW5kKzEsMippbmQrMik7Cn0KCi8qUXVlcnk6CjEgLT4gZ2V0IHdoaXRlIGNvdW50CjIgLT4gZ2V0IGJsYWNrIGNvdW50CjMgLT4gZ2V0IHN1bSB3aGl0ZQo0IC0+IGdldCBzdW0gYmxhY2sqLwoKbGwgcXVlcnlTZWdUcmVlKGxsIGluZCwgbGwgbG8sIGxsIGhpLCBsbCBsLCBsbCByLCBsbCBkKQp7CiAgICAvLyBjaGVjayBmb3IgdXBkYXRlCiAgICB1cGRhdGVfbGF6eShpbmQsbG8saGkpOwogICAgaWYgKGxvPnIgfHwgaGk8bCkgcmV0dXJuIDA7CiAgICBlbHNlIGlmIChsbz49bCAmJiBoaTw9cikKICAgIHsKICAgICAgICBpZiAoZD09MSkgcmV0dXJuIGFycltpbmRdLnc7CiAgICAgICAgZWxzZSBpZiAoZD09MikgcmV0dXJuIGFycltpbmRdLmI7CiAgICAgICAgZWxzZSBpZiAoZD09MykgcmV0dXJuIGFycltpbmRdLnN1bVc7CiAgICAgICAgZWxzZSByZXR1cm4gYXJyW2luZF0uc3VtQjsKICAgIH0KICAgIGxsIG1pZD0oaGkrbG8pLzI7CiAgICBsbCBsZWZ0PXF1ZXJ5U2VnVHJlZSgyKmluZCsxLGxvLG1pZCxsLHIsZCk7CiAgICBsbCByaWdodD1xdWVyeVNlZ1RyZWUoMippbmQrMixtaWQrMSxoaSxsLHIsZCk7CiAgICBsbCBhbnM9bGVmdCtyaWdodDsKICAgIHJldHVybiBhbnM7Cn0KCi8qVXBkYXRlOgoxIC0+IGZvcmNlIGFsbCB3aGl0ZQoyIC0+IGZvcmNlIGFsbCBibGFjayovCgp2b2lkIHVwZGF0ZVNlZ1RyZWUobGwgaW5kLCBsbCBsbywgbGwgaGksIGxsIGwsIGxsIHIsIGxsIHgpCnsKICAgIC8vIGNoZWNrIGZvciB1cGRhdGUKICAgIHVwZGF0ZV9sYXp5KGluZCxsbyxoaSk7CiAgICBpZiAobG8+ciB8fCBoaTxsKSByZXR1cm47CiAgICBlbHNlIGlmIChsbz49bCAmJiBoaTw9cikKICAgIHsKICAgICAgICBpZiAoeD09MSkKICAgICAgICB7CiAgICAgICAgICAgIGFycltpbmRdLncrPWFycltpbmRdLmI7CiAgICAgICAgICAgIGFycltpbmRdLnN1bVcrPWFycltpbmRdLnN1bUI7CiAgICAgICAgICAgIGFycltpbmRdLmI9YXJyW2luZF0uc3VtQj0wOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICBhcnJbaW5kXS5iKz1hcnJbaW5kXS53OwogICAgICAgICAgICBhcnJbaW5kXS5zdW1CKz1hcnJbaW5kXS5zdW1XOwogICAgICAgICAgICBhcnJbaW5kXS53PWFycltpbmRdLnN1bVc9MDsKICAgICAgICB9CiAgICAgICAgaWYgKGxvIT1oaSkgbGF6eWFyclsyKmluZCsxXT14LCBsYXp5YXJyWzIqaW5kKzJdPXg7CiAgICAgICAgcmV0dXJuOwogICAgfQogICAgbGwgbWlkPShoaStsbykvMjsKICAgIHVwZGF0ZVNlZ1RyZWUoMippbmQrMSxsbyxtaWQsbCxyLHgpOwogICAgdXBkYXRlU2VnVHJlZSgyKmluZCsyLG1pZCsxLGhpLGwscix4KTsKICAgIG1lcmdlKGluZCwyKmluZCsxLDIqaW5kKzIpOwp9Cgp2b2lkIGhsZF9xdWVyeTEoKQp7CiAgICBsbCBuPXN6KGhsZEFycik7CiAgICBsbCB4LHk7IGNpbj4+eD4+eTsgeC0tOyB5LS07CiAgICBsbCBsY2E9TENBKHgseSk7CiAgICBsbCB3aGl0ZUNudD0wLGJsYWNrQ250PTA7CiAgICBsbCBhPXgsYj15OwogICAgd2hpbGUgKGNoYWluW2FdIT1jaGFpbltsY2FdKQogICAgewogICAgICAgIHdoaXRlQ250Kz1xdWVyeVNlZ1RyZWUoMCwwLG4tMSxwb3NpdGlvbkluSGxkQXJyW2NoYWluSGVhZFtjaGFpblthXV1dLHBvc2l0aW9uSW5IbGRBcnJbYV0sMSk7CiAgICAgICAgYmxhY2tDbnQrPXF1ZXJ5U2VnVHJlZSgwLDAsbi0xLHBvc2l0aW9uSW5IbGRBcnJbY2hhaW5IZWFkW2NoYWluW2FdXV0scG9zaXRpb25JbkhsZEFyclthXSwyKTsKICAgICAgICBhPXVwW2NoYWluSGVhZFtjaGFpblthXV1dWzBdOwogICAgfQogICAgd2hpdGVDbnQrPXF1ZXJ5U2VnVHJlZSgwLDAsbi0xLHBvc2l0aW9uSW5IbGRBcnJbbGNhXSxwb3NpdGlvbkluSGxkQXJyW2FdLDEpOwogICAgYmxhY2tDbnQrPXF1ZXJ5U2VnVHJlZSgwLDAsbi0xLHBvc2l0aW9uSW5IbGRBcnJbbGNhXSxwb3NpdGlvbkluSGxkQXJyW2FdLDIpOwogICAgd2hpbGUgKGNoYWluW2JdIT1jaGFpbltsY2FdKQogICAgewogICAgICAgIHdoaXRlQ250Kz1xdWVyeVNlZ1RyZWUoMCwwLG4tMSxwb3NpdGlvbkluSGxkQXJyW2NoYWluSGVhZFtjaGFpbltiXV1dLHBvc2l0aW9uSW5IbGRBcnJbYl0sMSk7CiAgICAgICAgYmxhY2tDbnQrPXF1ZXJ5U2VnVHJlZSgwLDAsbi0xLHBvc2l0aW9uSW5IbGRBcnJbY2hhaW5IZWFkW2NoYWluW2JdXV0scG9zaXRpb25JbkhsZEFycltiXSwyKTsKICAgICAgICBiPXVwW2NoYWluSGVhZFtjaGFpbltiXV1dWzBdOwogICAgfQogICAgd2hpdGVDbnQrPXF1ZXJ5U2VnVHJlZSgwLDAsbi0xLHBvc2l0aW9uSW5IbGRBcnJbbGNhXSxwb3NpdGlvbkluSGxkQXJyW2JdLDEpOwogICAgYmxhY2tDbnQrPXF1ZXJ5U2VnVHJlZSgwLDAsbi0xLHBvc2l0aW9uSW5IbGRBcnJbbGNhXSxwb3NpdGlvbkluSGxkQXJyW2JdLDIpOwogICAgaWYgKHF1ZXJ5U2VnVHJlZSgwLDAsbi0xLHBvc2l0aW9uSW5IbGRBcnJbbGNhXSxwb3NpdGlvbkluSGxkQXJyW2xjYV0sMSk9PTEpIHdoaXRlQ250LS07CiAgICBlbHNlIGJsYWNrQ250LS07CiAgICBpZiAod2hpdGVDbnQ+YmxhY2tDbnQpCiAgICB7CiAgICAgICAgLy8gZm9yY2Ugd2hpdGUgaW4gcGF0aAogICAgICAgIGE9eCxiPXk7CiAgICAgICAgd2hpbGUgKGNoYWluW2FdIT1jaGFpbltsY2FdKQogICAgICAgIHsKICAgICAgICAgICAgdXBkYXRlU2VnVHJlZSgwLDAsbi0xLHBvc2l0aW9uSW5IbGRBcnJbY2hhaW5IZWFkW2NoYWluW2FdXV0scG9zaXRpb25JbkhsZEFyclthXSwxKTsKICAgICAgICAgICAgYT11cFtjaGFpbkhlYWRbY2hhaW5bYV1dXVswXTsKICAgICAgICB9CiAgICAgICAgdXBkYXRlU2VnVHJlZSgwLDAsbi0xLHBvc2l0aW9uSW5IbGRBcnJbbGNhXSxwb3NpdGlvbkluSGxkQXJyW2FdLDEpOwogICAgICAgIHdoaWxlIChjaGFpbltiXSE9Y2hhaW5bbGNhXSkKICAgICAgICB7CiAgICAgICAgICAgIHVwZGF0ZVNlZ1RyZWUoMCwwLG4tMSxwb3NpdGlvbkluSGxkQXJyW2NoYWluSGVhZFtjaGFpbltiXV1dLHBvc2l0aW9uSW5IbGRBcnJbYl0sMSk7CiAgICAgICAgICAgIGI9dXBbY2hhaW5IZWFkW2NoYWluW2JdXV1bMF07CiAgICAgICAgfQogICAgICAgIHVwZGF0ZVNlZ1RyZWUoMCwwLG4tMSxwb3NpdGlvbkluSGxkQXJyW2xjYV0scG9zaXRpb25JbkhsZEFycltiXSwxKTsKICAgIH0KICAgIGVsc2UgaWYgKGJsYWNrQ250PndoaXRlQ250KQogICAgewogICAgICAgIC8vIGZvcmNlIGJsYWNrIGluIHBhdGgKICAgICAgICBhPXgsYj15OwogICAgICAgIHdoaWxlIChjaGFpblthXSE9Y2hhaW5bbGNhXSkKICAgICAgICB7CiAgICAgICAgICAgIHVwZGF0ZVNlZ1RyZWUoMCwwLG4tMSxwb3NpdGlvbkluSGxkQXJyW2NoYWluSGVhZFtjaGFpblthXV1dLHBvc2l0aW9uSW5IbGRBcnJbYV0sMik7CiAgICAgICAgICAgIGE9dXBbY2hhaW5IZWFkW2NoYWluW2FdXV1bMF07CiAgICAgICAgfQogICAgICAgIHVwZGF0ZVNlZ1RyZWUoMCwwLG4tMSxwb3NpdGlvbkluSGxkQXJyW2xjYV0scG9zaXRpb25JbkhsZEFyclthXSwyKTsKICAgICAgICB3aGlsZSAoY2hhaW5bYl0hPWNoYWluW2xjYV0pCiAgICAgICAgewogICAgICAgICAgICB1cGRhdGVTZWdUcmVlKDAsMCxuLTEscG9zaXRpb25JbkhsZEFycltjaGFpbkhlYWRbY2hhaW5bYl1dXSxwb3NpdGlvbkluSGxkQXJyW2JdLDIpOwogICAgICAgICAgICBiPXVwW2NoYWluSGVhZFtjaGFpbltiXV1dWzBdOwogICAgICAgIH0KICAgICAgICB1cGRhdGVTZWdUcmVlKDAsMCxuLTEscG9zaXRpb25JbkhsZEFycltsY2FdLHBvc2l0aW9uSW5IbGRBcnJbYl0sMik7CiAgICB9Cn0KCnZvaWQgaGxkX3F1ZXJ5MigpCnsKICAgIGxsIG49c3ooaGxkQXJyKTsKICAgIGxsIHg7IGNpbj4+eDsgeC0tOwogICAgLy8gY29sb3Igc3VidHJlZSB4IHdpdGggYmxhY2sKICAgIHVwZGF0ZVNlZ1RyZWUoMCwwLG4tMSxpblRpbWVbeF0sb3V0VGltZVt4XSwyKTsKfQoKbGwgaGxkX3F1ZXJ5MygpCnsKICAgIGxsIG49c3ooaGxkQXJyKTsKICAgIGxsIHgseTsgY2luPj54Pj55OyB4LS07IHktLTsKICAgIGxsIGxjYT1MQ0EoeCx5KTsKICAgIGxsIHdoaXRlU3VtPTAsYmxhY2tTdW09MDsKICAgIGxsIGE9eCxiPXk7CiAgICB3aGlsZSAoY2hhaW5bYV0hPWNoYWluW2xjYV0pCiAgICB7CiAgICAgICAgd2hpdGVTdW0rPXF1ZXJ5U2VnVHJlZSgwLDAsbi0xLHBvc2l0aW9uSW5IbGRBcnJbY2hhaW5IZWFkW2NoYWluW2FdXV0scG9zaXRpb25JbkhsZEFyclthXSwzKTsKICAgICAgICBibGFja1N1bSs9cXVlcnlTZWdUcmVlKDAsMCxuLTEscG9zaXRpb25JbkhsZEFycltjaGFpbkhlYWRbY2hhaW5bYV1dXSxwb3NpdGlvbkluSGxkQXJyW2FdLDQpOwogICAgICAgIGE9dXBbY2hhaW5IZWFkW2NoYWluW2FdXV1bMF07CiAgICB9CiAgICB3aGl0ZVN1bSs9cXVlcnlTZWdUcmVlKDAsMCxuLTEscG9zaXRpb25JbkhsZEFycltsY2FdLHBvc2l0aW9uSW5IbGRBcnJbYV0sMyk7CiAgICBibGFja1N1bSs9cXVlcnlTZWdUcmVlKDAsMCxuLTEscG9zaXRpb25JbkhsZEFycltsY2FdLHBvc2l0aW9uSW5IbGRBcnJbYV0sNCk7CiAgICB3aGlsZSAoY2hhaW5bYl0hPWNoYWluW2xjYV0pCiAgICB7CiAgICAgICAgd2hpdGVTdW0rPXF1ZXJ5U2VnVHJlZSgwLDAsbi0xLHBvc2l0aW9uSW5IbGRBcnJbY2hhaW5IZWFkW2NoYWluW2JdXV0scG9zaXRpb25JbkhsZEFycltiXSwzKTsKICAgICAgICBibGFja1N1bSs9cXVlcnlTZWdUcmVlKDAsMCxuLTEscG9zaXRpb25JbkhsZEFycltjaGFpbkhlYWRbY2hhaW5bYl1dXSxwb3NpdGlvbkluSGxkQXJyW2JdLDQpOwogICAgICAgIGI9dXBbY2hhaW5IZWFkW2NoYWluW2JdXV1bMF07CiAgICB9CiAgICB3aGl0ZVN1bSs9cXVlcnlTZWdUcmVlKDAsMCxuLTEscG9zaXRpb25JbkhsZEFycltsY2FdLHBvc2l0aW9uSW5IbGRBcnJbYl0sMyk7CiAgICBibGFja1N1bSs9cXVlcnlTZWdUcmVlKDAsMCxuLTEscG9zaXRpb25JbkhsZEFycltsY2FdLHBvc2l0aW9uSW5IbGRBcnJbYl0sNCk7CiAgICBpZiAocXVlcnlTZWdUcmVlKDAsMCxuLTEscG9zaXRpb25JbkhsZEFycltsY2FdLHBvc2l0aW9uSW5IbGRBcnJbbGNhXSwxKT09MSkgd2hpdGVTdW0tPXZhbFtsY2FdOwogICAgZWxzZSBibGFja1N1bS09dmFsW2xjYV07CiAgICByZXR1cm4gbWF4KHdoaXRlU3VtLGJsYWNrU3VtKTsKfQoKdm9pZCBzb2x2ZSgpCnsKICAgIGxsIG4sbTsgY2luPj5uPj5tOwogICAgaGxkQXJyLnJlc2l6ZShuKTsKICAgIGhsZFZhbEFyci5yZXNpemUobik7CiAgICB2bGwgYWRqW25dOwogICAgZm9yIChsbCBpPTA7aTxuLTE7aSsrKQogICAgewogICAgICAgIGxsIHUsdjsgY2luPj51Pj52OyB1LS07IHYtLTsKICAgICAgICBhZGpbdV0ucHVzaF9iYWNrKHYpOwogICAgICAgIGFkalt2XS5wdXNoX2JhY2sodSk7CiAgICB9CiAgICB2YWwucmVzaXplKG4pOyBjaW4+PnZhbDsKICAgIGNvbG9yLnJlc2l6ZShuLDApOwogICAgcGFyZW50LnJlc2l6ZShuKTsKICAgIHNidHJlZVNpemUucmVzaXplKG4pOwogICAgbHZsLnJlc2l6ZShuKTsKICAgIGNoYWluLnJlc2l6ZShuKTsKICAgIGNoYWluSGVhZC5yZXNpemUobik7CiAgICBwb3NpdGlvbkluSGxkQXJyLnJlc2l6ZShuKTsKICAgIGluVGltZS5yZXNpemUobik7CiAgICBvdXRUaW1lLnJlc2l6ZShuKTsKICAgIHVwLnJlc2l6ZShuLCB2bGwgKDIwLC0xKSk7CiAgICBhcnIucmVzaXplKDQqbik7CiAgICBsYXp5YXJyLnJlc2l6ZSg0Km4sMCk7CiAgICBkZnMoMCwtMSwwLGFkaik7CiAgICBwb3M9Y2hhaW5JZD0wOwogICAgSExEKDAsLTEsYWRqKTsKICAgIGRlYnVnKGhsZEFycik7CiAgICBkZWJ1ZyhobGRWYWxBcnIpOwogICAgZGVidWcoaW5UaW1lKTsKICAgIGRlYnVnKG91dFRpbWUpOwogICAgYnVpbGRTZWdUcmVlKDAsMCxuLTEpOwogICAgd2hpbGUgKG0tLSkKICAgIHsKICAgICAgICBsbCBxOyBjaW4+PnE7CiAgICAgICAgaWYgKHE9PTEpIGhsZF9xdWVyeTEoKTsKICAgICAgICBlbHNlIGlmIChxPT0yKSBobGRfcXVlcnkyKCk7CiAgICAgICAgZWxzZSBjb3V0PDxobGRfcXVlcnkzKCk8PGVuZGw7CiAgICB9Cn0KCmludCBtYWluKCkKewogICAgI2lmbmRlZiBPTkxJTkVfSlVER0UKICAgICAgICAvLyBmcmVvcGVuKCJpbnB1dC50eHQiLCJyIixzdGRpbik7CiAgICAgICAgLy8gZnJlb3Blbigib3V0cHV0LnR4dCIsInciLHN0ZG91dCk7CiAgICAgICAgZnJlb3BlbigiZXJyb3IudHh0IiwidyIsc3RkZXJyKTsKICAgICAgICBjbG9ja190IGNsayA9IGNsb2NrKCk7CiAgICAjZW5kaWYKICAgIC8vIGluaXRfdXNhY28oKTsKICAgIGZhc3RJTzsKICAgIGludCB0PTE7CiAgICAvLyBjaW4+PnQ7CiAgICBmb3IgKGludCB0ZXN0PTE7dGVzdDw9dDt0ZXN0KyspCiAgICB7CiAgICAgICAgLy8gY291dDw8IkNhc2UgIyI8PHRlc3Q8PCI6ICI7CiAgICAgICAgc29sdmUoKTsKICAgICAgICBjb3V0PDxlbmRsOwogICAgfQogICAgI2lmbmRlZiBPTkxJTkVfSlVER0UKICAgICAgICAgIGNlcnIgPDwgJ1xuJzw8IlRpbWUgKGluIHMpOiAiIDw8IGRvdWJsZShjbG9jaygpIC0gY2xrKSAqIDEuMCAvIENMT0NLU19QRVJfU0VDIDw8ICdcbic7CiAgICAjZW5kaWYKICAgIHJldHVybiAwOwp9Cg==