#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using db = double;
using str = string; // yay python!
using pi = pair<int,int>;
using pl = pair<ll,ll>;
using pd = pair<db,db>;
using vi = vector<int>;
using vb = vector<bool>;
using vl = vector<ll>;
using vd = vector<db>;
using vs = vector<str>;
using vpi = vector<pi>;
using vpl = vector<pl>;
using vpd = vector<pd>;
#define tcT template<class T
// ^ lol this makes everything look weird but I'll try it
tcT> using V = vector<T>;
tcT, size_t SZ> using AR = array<T,SZ>;
// pairs
#define mp make_pair
#define f first
#define s second
// vectors
#define sz(x) (int)(x).size()
#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define sor(x) sort(all(x))
#define rsz resize
#define ins insert
#define ft front()
#define bk back()
#define pf push_front
#define pb push_back
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound
// loops
#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define F0R(i,a) FOR(i,0,a)
#define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i,a) ROF(i,0,a)
#define trav(a,x) for (auto& a: x)
const int MOD = 1e9+7; // 998244353;
const int MX = 50005;
const ll INF = 1e18; // not too close to LLONG_MAX
const ld PI = acos((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1}; // for every grid problem!!
mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());
// helper funcs
constexpr int pct(int x) { return __builtin_popcount(x); } // # of bits set
constexpr int bits(int x) { return 31-__builtin_clz(x); } // floor(log2(x))
ll cdiv(ll a, ll b) { return a/b+((a^b)>0&&a%b); } // divide a by b rounded up
ll fdiv(ll a, ll b) { return a/b-((a^b)<0&&a%b); } // divide a by b rounded down
ll half(ll x) { return fdiv(x,2); }
tcT> bool ckmin(T& a, const T& b) {
return b < a ? a = b, 1 : 0; } // set a = min(a,b)
tcT> bool ckmax(T& a, const T& b) {
return a < b ? a = b, 1 : 0; }
#define tcTU tcT, class U
tcTU> T fstTrue(T lo, T hi, U f) {
// note: if (lo+hi)/2 is used instead of half(lo+hi)
// then this will loop infinitely when lo=hi
hi ++; assert(lo <= hi); // assuming f is increasing
while (lo < hi) { // find first index such that f is true
T mid = half(lo+hi);
f(mid) ? hi = mid : lo = mid+1;
}
return lo;
}
tcTU> T lstTrue(T lo, T hi, U f) {
lo --; assert(lo <= hi); // assuming f is decreasing
while (lo < hi) { // find first index such that f is true
T mid = half(lo+hi+1);
f(mid) ? lo = mid : hi = mid-1;
}
return lo;
}
tcT> void remDup(vector<T>& v) { // sort and remove duplicates
sort(all(v)); v.erase(unique(all(v)),end(v)); }
tcTU> void erase(T& t, const U& u) { // don't erase
auto it = t.find(u); assert(it != end(t));
t.erase(u); } // element that doesn't exist from (multi)set
// INPUT
#define tcTUU tcT, class ...U
tcT> void re(complex<T>& c);
tcTU> void re(pair<T,U>& p);
tcT> void re(vector<T>& v);
tcT, size_t SZ> void re(AR<T,SZ>& a);
tcT> void re(T& x) { cin >> x; }
void re(db& d) { str t; re(t); d = stod(t); }
void re(ld& d) { str t; re(t); d = stold(t); }
tcTUU> void re(T& t, U&... u) { re(t); re(u...); }
tcT> void re(complex<T>& c) { T a,b; re(a,b); c = {a,b}; }
tcTU> void re(pair<T,U>& p) { re(p.f,p.s); }
tcT> void re(vector<T>& x) { trav(a,x) re(a); }
tcT, size_t SZ> void re(AR<T,SZ>& x) { trav(a,x) re(a); }
// TO_STRING
#define ts to_string
str ts(char c) { return str(1,c); }
str ts(const char* s) { return (str)s; }
str ts(str s) { return s; }
str ts(bool b) {
#ifdef LOCAL
return b ? "true" : "false";
#else
return ts((int)b);
#endif
}
tcT> str ts(complex<T> c) {
stringstream ss; ss << c; return ss.str(); }
str ts(vector<bool> v) {
str res = "{"; F0R(i,sz(v)) res += char('0'+v[i]);
res += "}"; return res; }
template<size_t SZ> str ts(bitset<SZ> b) {
str res = ""; F0R(i,SZ) res += char('0'+b[i]);
return res; }
tcTU> str ts(pair<T,U> p);
tcT> str ts(T v) { // containers with begin(), end()
#ifdef LOCAL
bool fst = 1; str res = "{";
for (const auto& x: v) {
if (!fst) res += ", ";
fst = 0; res += ts(x);
}
res += "}"; return res;
#else
bool fst = 1; str res = "";
for (const auto& x: v) {
if (!fst) res += " ";
fst = 0; res += ts(x);
}
return res;
#endif
}
tcTU> str ts(pair<T,U> p) {
#ifdef LOCAL
return "("+ts(p.f)+", "+ts(p.s)+")";
#else
return ts(p.f)+" "+ts(p.s);
#endif
}
// OUTPUT
tcT> void pr(T x) { cout << ts(x); }
tcTUU> void pr(const T& t, const U&... u) {
pr(t); pr(u...); }
void ps() { pr("\n"); } // print w/ spaces
tcTUU> void ps(const T& t, const U&... u) {
pr(t); if (sizeof...(u)) pr(" "); ps(u...); }
// DEBUG
void DBG() { cerr << "]" << endl; }
tcTUU> void DBG(const T& t, const U&... u) {
cerr << ts(t); if (sizeof...(u)) cerr << ", ";
DBG(u...); }
#ifdef LOCAL // compile with -DLOCAL, chk -> fake assert
#define dbg(...) cerr << "Line(" << __LINE__ << ") -> [" << #__VA_ARGS__ << "]: [", DBG(__VA_ARGS__)
#define chk(...) if (!(__VA_ARGS__)) cerr << "Line(" << __LINE__ << ") -> function(" \
<< __FUNCTION__ << ") -> CHK FAILED: (" << #__VA_ARGS__ << ")" << "\n", exit(0);
#else
#define dbg(...) 0
#define chk(...) 0
#endif
// FILE I/O
void setIn(str s) { freopen(s.c_str(),"r",stdin); }
void setOut(str s) { freopen(s.c_str(),"w",stdout); }
void unsyncIO() { cin.tie(0)->sync_with_stdio(0); }
void setIO(str s = "") {
unsyncIO();
// cin.exceptions(cin.failbit);
// throws exception when do smth illegal
// ex. try to read letter into int
if (sz(s)) { setIn(s+".in"), setOut(s+".out"); } // for USACO
}
/**
* Description: 1D range increment and sum query.
* Source: USACO Counting Haybales
* Verification: SPOJ Horrible
*/
template<class T, int SZ> struct LazySeg {
static_assert(pct(SZ) == 1); // SZ must be power of 2
const T ID = {{0,0}};
T comb(T a, T b) { return {a[0]+b[0],a[1]+b[1]}; }
T seg[2*SZ];
int lazy[2*SZ];
LazySeg() {
F0R(i,2*SZ) seg[i] = ID;
}
void push(int ind, int L, int R) { /// modify values for current node
if (!lazy[ind]) return;
swap(seg[ind][0],seg[ind][1]);
// seg[ind] += (R-L+1)*lazy[ind]; // dependent on operation
if (L != R) F0R(i,2) lazy[2*ind+i] ^= lazy[ind]; /// prop to children
lazy[ind] = 0;
} // recalc values for current node
void pull(int ind) { seg[ind] = comb(seg[2*ind],seg[2*ind+1]); }
void build() { ROF(i,1,SZ) pull(i); }
void upd(int lo,int hi,int ind=1,int L=0, int R=SZ-1) {
push(ind,L,R); if (hi < L || R < lo) return;
if (lo <= L && R <= hi) {
lazy[ind] = 1; push(ind,L,R); return; }
int M = (L+R)/2;
upd(lo,hi,2*ind,L,M);
upd(lo,hi,2*ind+1,M+1,R);
pull(ind);
}
T query(int lo, int hi, int ind=1, int L=0, int R=SZ-1) {
push(ind,L,R); if (lo > R || L > hi) return ID;
if (lo <= L && R <= hi) return seg[ind];
int M = (L+R)/2;
return comb(query(lo,hi,2*ind,L,M),query(lo,hi,2*ind+1,M+1,R));
}
};
LazySeg<AR<int,2>,1<<16> L;
/**
* Description: Heavy-Light Decomposition, add val to verts
* and query sum in path/subtree.
* Time: any tree path is split into $O(\log N)$ parts
* Source: http://c...content-available-to-author-only...s.com/blog/entry/22072, https://c...content-available-to-author-only...s.com/blog/entry/53170
* Verification: *
*/
// #include "../../data-structures/1D Range Queries (9.2)/LazySeg (15.2).h"
const int SZ = 50005;
vi adj[SZ];
int par[SZ], root[SZ], depth[SZ], sz[SZ], ti;
int pos[SZ]; vi rpos; // rpos not used, but could be useful
ll stor[MX];
template<int SZ, bool VALS_IN_EDGES> struct HLD {
void ae(int x, int y) { adj[x].pb(y), adj[y].pb(x); }
void dfsSz(int x) {
sz[x] = 1;
trav(y,adj[x]) {
par[y] = x; depth[y] = depth[x]+1;
adj[y].erase(find(all(adj[y]),x)); // remove parent from adj list
dfsSz(y); sz[x] += sz[y];
if (sz[y] > sz[adj[x][0]]) swap(y,adj[x][0]);
}
}
void dfsHld(int x) {
pos[x] = ti++; rpos.pb(x);
trav(y,adj[x]) {
root[y] = (y == adj[x][0] ? root[x] : y);
dfsHld(y); }
}
void init() {
int R = 0;
par[R] = depth[R] = ti = 0; dfsSz(R);
root[R] = R; dfsHld(R);
}
int lca(int x, int y) {
for (; root[x] != root[y]; y = par[root[y]])
if (depth[root[x]] > depth[root[y]]) swap(x,y);
return depth[x] < depth[y] ? x : y;
}
/// int dist(int x, int y) { // # edges on path
/// return depth[x]+depth[y]-2*depth[lca(x,y)]; }
// LazySeg<ll,SZ> tree; // segtree for sum
// template <class BinaryOp>
// void processPath(int x, int y, BinaryOp op) {
// for (; root[x] != root[y]; y = par[root[y]]) {
// if (depth[root[x]] > depth[root[y]]) swap(x,y);
// op(pos[root[y]],pos[y]); }
// if (depth[x] > depth[y]) swap(x,y);
// op(pos[x]+VALS_IN_EDGES,pos[y]);
// }
// void modifyPath(int x, int y, int v) {
// processPath(x,y,[this,&v](int l, int r) {
// tree.upd(l,r,v); }); }
// ll queryPath(int x, int y) {
// ll res = 0; processPath(x,y,[this,&res](int l, int r) {
// res += tree.query(l,r); });
// return res; }
// void modifySubtree(int x, int v) {
// tree.upd(pos[x]+VALS_IN_EDGES,pos[x]+sz[x]-1,v); }
};
ll sq(int x) {
ll num = L.query(pos[x],pos[x]+sz[x]-1)[1];
return num*(num-1)/2;
}
HLD<50005,0> H;
int N,Q,A[MX];
// vi child[MX];
void flip(int x) {
for (int y = x; 0 != root[y]; y = par[root[y]]) {
int p = par[root[y]];
stor[p] -= sq(root[y]);
}
for (int y = x; ; y = par[root[y]]) {
if (root[y] == 0) {
L.upd(pos[0],pos[y]);
break;
} else {
L.upd(pos[root[y]],pos[y]);
}
}
for (int y = x; 0 != root[y]; y = par[root[y]]) {
int p = par[root[y]];
stor[p] += sq(root[y]);
}
}
int main() {
setIO(); re(N,Q);
F0R(i,N) re(A[i]);
F0R(i,N-1) {
int u,v; re(u,v); u--,v--;
H.ae(u,v);
}
H.init();
F0R(i,N) {
L.seg[(1<<16)+pos[i]][A[i]] = 1;
}
L.build();
F0R(i,N) {
FOR(j,1,sz(adj[i])) stor[i] += sq(adj[i][j]);
}
// F0R(i,N) dbg(i,sq(i));
F0R(i,Q) {
int o,x; re(o,x); x --;
if (o == 1) {
flip(x);
} else {
ll ans = sq(x)-stor[x];
if (sz(adj[x])) ans -= sq(adj[x][0]);
ps(ans);
}
}
// HLD? block tree?
// you should actually read the stuff at the bottom
}
/* stuff you should look for
* int overflow, array bounds
* special cases (n=1?)
* do smth instead of nothing and stay organized
* WRITE STUFF DOWN
* DON'T GET STUCK ON ONE APPROACH
*/
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CiAKdXNpbmcgbGwgPSBsb25nIGxvbmc7CnVzaW5nIGxkID0gbG9uZyBkb3VibGU7CnVzaW5nIGRiID0gZG91YmxlOyAKdXNpbmcgc3RyID0gc3RyaW5nOyAvLyB5YXkgcHl0aG9uIQoKdXNpbmcgcGkgPSBwYWlyPGludCxpbnQ+Owp1c2luZyBwbCA9IHBhaXI8bGwsbGw+Owp1c2luZyBwZCA9IHBhaXI8ZGIsZGI+OwoKdXNpbmcgdmkgPSB2ZWN0b3I8aW50PjsKdXNpbmcgdmIgPSB2ZWN0b3I8Ym9vbD47CnVzaW5nIHZsID0gdmVjdG9yPGxsPjsKdXNpbmcgdmQgPSB2ZWN0b3I8ZGI+OyAKdXNpbmcgdnMgPSB2ZWN0b3I8c3RyPjsKdXNpbmcgdnBpID0gdmVjdG9yPHBpPjsKdXNpbmcgdnBsID0gdmVjdG9yPHBsPjsgCnVzaW5nIHZwZCA9IHZlY3RvcjxwZD47CgojZGVmaW5lIHRjVCB0ZW1wbGF0ZTxjbGFzcyBUCi8vIF4gbG9sIHRoaXMgbWFrZXMgZXZlcnl0aGluZyBsb29rIHdlaXJkIGJ1dCBJJ2xsIHRyeSBpdAp0Y1Q+IHVzaW5nIFYgPSB2ZWN0b3I8VD47IAp0Y1QsIHNpemVfdCBTWj4gdXNpbmcgQVIgPSBhcnJheTxULFNaPjsgCgovLyBwYWlycwojZGVmaW5lIG1wIG1ha2VfcGFpcgojZGVmaW5lIGYgZmlyc3QKI2RlZmluZSBzIHNlY29uZAoKLy8gdmVjdG9ycwojZGVmaW5lIHN6KHgpIChpbnQpKHgpLnNpemUoKQojZGVmaW5lIGFsbCh4KSBiZWdpbih4KSwgZW5kKHgpCiNkZWZpbmUgcmFsbCh4KSAoeCkucmJlZ2luKCksICh4KS5yZW5kKCkgCiNkZWZpbmUgc29yKHgpIHNvcnQoYWxsKHgpKSAKI2RlZmluZSByc3ogcmVzaXplCiNkZWZpbmUgaW5zIGluc2VydCAKI2RlZmluZSBmdCBmcm9udCgpIAojZGVmaW5lIGJrIGJhY2soKQojZGVmaW5lIHBmIHB1c2hfZnJvbnQgCiNkZWZpbmUgcGIgcHVzaF9iYWNrCiNkZWZpbmUgZWIgZW1wbGFjZV9iYWNrIAojZGVmaW5lIGxiIGxvd2VyX2JvdW5kIAojZGVmaW5lIHViIHVwcGVyX2JvdW5kIAoKLy8gbG9vcHMKI2RlZmluZSBGT1IoaSxhLGIpIGZvciAoaW50IGkgPSAoYSk7IGkgPCAoYik7ICsraSkKI2RlZmluZSBGMFIoaSxhKSBGT1IoaSwwLGEpCiNkZWZpbmUgUk9GKGksYSxiKSBmb3IgKGludCBpID0gKGIpLTE7IGkgPj0gKGEpOyAtLWkpCiNkZWZpbmUgUjBGKGksYSkgUk9GKGksMCxhKQojZGVmaW5lIHRyYXYoYSx4KSBmb3IgKGF1dG8mIGE6IHgpCgpjb25zdCBpbnQgTU9EID0gMWU5Kzc7IC8vIDk5ODI0NDM1MzsKY29uc3QgaW50IE1YID0gNTAwMDU7CmNvbnN0IGxsIElORiA9IDFlMTg7IC8vIG5vdCB0b28gY2xvc2UgdG8gTExPTkdfTUFYCmNvbnN0IGxkIFBJID0gYWNvcygobGQpLTEpOwpjb25zdCBpbnQgeGRbNF0gPSB7MSwwLC0xLDB9LCB5ZFs0XSA9IHswLDEsMCwtMX07IC8vIGZvciBldmVyeSBncmlkIHByb2JsZW0hIQptdDE5OTM3IHJuZygodWludDMyX3QpY2hyb25vOjpzdGVhZHlfY2xvY2s6Om5vdygpLnRpbWVfc2luY2VfZXBvY2goKS5jb3VudCgpKTsgCgovLyBoZWxwZXIgZnVuY3MKY29uc3RleHByIGludCBwY3QoaW50IHgpIHsgcmV0dXJuIF9fYnVpbHRpbl9wb3Bjb3VudCh4KTsgfSAvLyAjIG9mIGJpdHMgc2V0CmNvbnN0ZXhwciBpbnQgYml0cyhpbnQgeCkgeyByZXR1cm4gMzEtX19idWlsdGluX2Nseih4KTsgfSAvLyBmbG9vcihsb2cyKHgpKSAKbGwgY2RpdihsbCBhLCBsbCBiKSB7IHJldHVybiBhL2IrKChhXmIpPjAmJmElYik7IH0gLy8gZGl2aWRlIGEgYnkgYiByb3VuZGVkIHVwCmxsIGZkaXYobGwgYSwgbGwgYikgeyByZXR1cm4gYS9iLSgoYV5iKTwwJiZhJWIpOyB9IC8vIGRpdmlkZSBhIGJ5IGIgcm91bmRlZCBkb3duCmxsIGhhbGYobGwgeCkgeyByZXR1cm4gZmRpdih4LDIpOyB9Cgp0Y1Q+IGJvb2wgY2ttaW4oVCYgYSwgY29uc3QgVCYgYikgewoJcmV0dXJuIGIgPCBhID8gYSA9IGIsIDEgOiAwOyB9IC8vIHNldCBhID0gbWluKGEsYikKdGNUPiBib29sIGNrbWF4KFQmIGEsIGNvbnN0IFQmIGIpIHsKCXJldHVybiBhIDwgYiA/IGEgPSBiLCAxIDogMDsgfQoKI2RlZmluZSB0Y1RVIHRjVCwgY2xhc3MgVQp0Y1RVPiBUIGZzdFRydWUoVCBsbywgVCBoaSwgVSBmKSB7IAoJLy8gbm90ZTogaWYgKGxvK2hpKS8yIGlzIHVzZWQgaW5zdGVhZCBvZiBoYWxmKGxvK2hpKSAKCS8vIHRoZW4gdGhpcyB3aWxsIGxvb3AgaW5maW5pdGVseSB3aGVuIGxvPWhpCgloaSArKzsgYXNzZXJ0KGxvIDw9IGhpKTsgLy8gYXNzdW1pbmcgZiBpcyBpbmNyZWFzaW5nCgl3aGlsZSAobG8gPCBoaSkgeyAvLyBmaW5kIGZpcnN0IGluZGV4IHN1Y2ggdGhhdCBmIGlzIHRydWUgCgkJVCBtaWQgPSBoYWxmKGxvK2hpKTsKCQlmKG1pZCkgPyBoaSA9IG1pZCA6IGxvID0gbWlkKzE7IAoJfSAKCXJldHVybiBsbzsKfQp0Y1RVPiBUIGxzdFRydWUoVCBsbywgVCBoaSwgVSBmKSB7CglsbyAtLTsgYXNzZXJ0KGxvIDw9IGhpKTsgLy8gYXNzdW1pbmcgZiBpcyBkZWNyZWFzaW5nCgl3aGlsZSAobG8gPCBoaSkgeyAvLyBmaW5kIGZpcnN0IGluZGV4IHN1Y2ggdGhhdCBmIGlzIHRydWUgCgkJVCBtaWQgPSBoYWxmKGxvK2hpKzEpOwoJCWYobWlkKSA/IGxvID0gbWlkIDogaGkgPSBtaWQtMTsKCX0gCglyZXR1cm4gbG87Cn0KdGNUPiB2b2lkIHJlbUR1cCh2ZWN0b3I8VD4mIHYpIHsgLy8gc29ydCBhbmQgcmVtb3ZlIGR1cGxpY2F0ZXMKCXNvcnQoYWxsKHYpKTsgdi5lcmFzZSh1bmlxdWUoYWxsKHYpKSxlbmQodikpOyB9CnRjVFU+IHZvaWQgZXJhc2UoVCYgdCwgY29uc3QgVSYgdSkgeyAvLyBkb24ndCBlcmFzZQoJYXV0byBpdCA9IHQuZmluZCh1KTsgYXNzZXJ0KGl0ICE9IGVuZCh0KSk7Cgl0LmVyYXNlKHUpOyB9IC8vIGVsZW1lbnQgdGhhdCBkb2Vzbid0IGV4aXN0IGZyb20gKG11bHRpKXNldAoKLy8gSU5QVVQKI2RlZmluZSB0Y1RVVSB0Y1QsIGNsYXNzIC4uLlUKdGNUPiB2b2lkIHJlKGNvbXBsZXg8VD4mIGMpOwp0Y1RVPiB2b2lkIHJlKHBhaXI8VCxVPiYgcCk7CnRjVD4gdm9pZCByZSh2ZWN0b3I8VD4mIHYpOwp0Y1QsIHNpemVfdCBTWj4gdm9pZCByZShBUjxULFNaPiYgYSk7Cgp0Y1Q+IHZvaWQgcmUoVCYgeCkgeyBjaW4gPj4geDsgfQp2b2lkIHJlKGRiJiBkKSB7IHN0ciB0OyByZSh0KTsgZCA9IHN0b2QodCk7IH0Kdm9pZCByZShsZCYgZCkgeyBzdHIgdDsgcmUodCk7IGQgPSBzdG9sZCh0KTsgfQp0Y1RVVT4gdm9pZCByZShUJiB0LCBVJi4uLiB1KSB7IHJlKHQpOyByZSh1Li4uKTsgfQoKdGNUPiB2b2lkIHJlKGNvbXBsZXg8VD4mIGMpIHsgVCBhLGI7IHJlKGEsYik7IGMgPSB7YSxifTsgfQp0Y1RVPiB2b2lkIHJlKHBhaXI8VCxVPiYgcCkgeyByZShwLmYscC5zKTsgfQp0Y1Q+IHZvaWQgcmUodmVjdG9yPFQ+JiB4KSB7IHRyYXYoYSx4KSByZShhKTsgfQp0Y1QsIHNpemVfdCBTWj4gdm9pZCByZShBUjxULFNaPiYgeCkgeyB0cmF2KGEseCkgcmUoYSk7IH0KCi8vIFRPX1NUUklORwojZGVmaW5lIHRzIHRvX3N0cmluZwpzdHIgdHMoY2hhciBjKSB7IHJldHVybiBzdHIoMSxjKTsgfQpzdHIgdHMoY29uc3QgY2hhciogcykgeyByZXR1cm4gKHN0cilzOyB9CnN0ciB0cyhzdHIgcykgeyByZXR1cm4gczsgfQpzdHIgdHMoYm9vbCBiKSB7IAoJI2lmZGVmIExPQ0FMCgkJcmV0dXJuIGIgPyAidHJ1ZSIgOiAiZmFsc2UiOyAKCSNlbHNlIAoJCXJldHVybiB0cygoaW50KWIpOwoJI2VuZGlmCn0KdGNUPiBzdHIgdHMoY29tcGxleDxUPiBjKSB7IAoJc3RyaW5nc3RyZWFtIHNzOyBzcyA8PCBjOyByZXR1cm4gc3Muc3RyKCk7IH0Kc3RyIHRzKHZlY3Rvcjxib29sPiB2KSB7CglzdHIgcmVzID0gInsiOyBGMFIoaSxzeih2KSkgcmVzICs9IGNoYXIoJzAnK3ZbaV0pOwoJcmVzICs9ICJ9IjsgcmV0dXJuIHJlczsgfQp0ZW1wbGF0ZTxzaXplX3QgU1o+IHN0ciB0cyhiaXRzZXQ8U1o+IGIpIHsKCXN0ciByZXMgPSAiIjsgRjBSKGksU1opIHJlcyArPSBjaGFyKCcwJytiW2ldKTsKCXJldHVybiByZXM7IH0KdGNUVT4gc3RyIHRzKHBhaXI8VCxVPiBwKTsKdGNUPiBzdHIgdHMoVCB2KSB7IC8vIGNvbnRhaW5lcnMgd2l0aCBiZWdpbigpLCBlbmQoKQoJI2lmZGVmIExPQ0FMCgkJYm9vbCBmc3QgPSAxOyBzdHIgcmVzID0gInsiOwoJCWZvciAoY29uc3QgYXV0byYgeDogdikgewoJCQlpZiAoIWZzdCkgcmVzICs9ICIsICI7CgkJCWZzdCA9IDA7IHJlcyArPSB0cyh4KTsKCQl9CgkJcmVzICs9ICJ9IjsgcmV0dXJuIHJlczsKCSNlbHNlCgkJYm9vbCBmc3QgPSAxOyBzdHIgcmVzID0gIiI7CgkJZm9yIChjb25zdCBhdXRvJiB4OiB2KSB7CgkJCWlmICghZnN0KSByZXMgKz0gIiAiOwoJCQlmc3QgPSAwOyByZXMgKz0gdHMoeCk7CgkJfQoJCXJldHVybiByZXM7CgoJI2VuZGlmCn0KdGNUVT4gc3RyIHRzKHBhaXI8VCxVPiBwKSB7CgkjaWZkZWYgTE9DQUwKCQlyZXR1cm4gIigiK3RzKHAuZikrIiwgIit0cyhwLnMpKyIpIjsgCgkjZWxzZQoJCXJldHVybiB0cyhwLmYpKyIgIit0cyhwLnMpOwoJI2VuZGlmCn0KCi8vIE9VVFBVVAp0Y1Q+IHZvaWQgcHIoVCB4KSB7IGNvdXQgPDwgdHMoeCk7IH0KdGNUVVU+IHZvaWQgcHIoY29uc3QgVCYgdCwgY29uc3QgVSYuLi4gdSkgeyAKCXByKHQpOyBwcih1Li4uKTsgfQp2b2lkIHBzKCkgeyBwcigiXG4iKTsgfSAvLyBwcmludCB3LyBzcGFjZXMKdGNUVVU+IHZvaWQgcHMoY29uc3QgVCYgdCwgY29uc3QgVSYuLi4gdSkgeyAKCXByKHQpOyBpZiAoc2l6ZW9mLi4uKHUpKSBwcigiICIpOyBwcyh1Li4uKTsgfQoKLy8gREVCVUcKdm9pZCBEQkcoKSB7IGNlcnIgPDwgIl0iIDw8IGVuZGw7IH0KdGNUVVU+IHZvaWQgREJHKGNvbnN0IFQmIHQsIGNvbnN0IFUmLi4uIHUpIHsKCWNlcnIgPDwgdHModCk7IGlmIChzaXplb2YuLi4odSkpIGNlcnIgPDwgIiwgIjsKCURCRyh1Li4uKTsgfQojaWZkZWYgTE9DQUwgLy8gY29tcGlsZSB3aXRoIC1ETE9DQUwsIGNoayAtPiBmYWtlIGFzc2VydAoJI2RlZmluZSBkYmcoLi4uKSBjZXJyIDw8ICJMaW5lKCIgPDwgX19MSU5FX18gPDwgIikgLT4gWyIgPDwgI19fVkFfQVJHU19fIDw8ICJdOiBbIiwgREJHKF9fVkFfQVJHU19fKQoJI2RlZmluZSBjaGsoLi4uKSBpZiAoIShfX1ZBX0FSR1NfXykpIGNlcnIgPDwgIkxpbmUoIiA8PCBfX0xJTkVfXyA8PCAiKSAtPiBmdW5jdGlvbigiIFwKCQkgPDwgX19GVU5DVElPTl9fICA8PCAiKSAtPiBDSEsgRkFJTEVEOiAoIiA8PCAjX19WQV9BUkdTX18gPDwgIikiIDw8ICJcbiIsIGV4aXQoMCk7CiNlbHNlCgkjZGVmaW5lIGRiZyguLi4pIDAKCSNkZWZpbmUgY2hrKC4uLikgMAojZW5kaWYKCi8vIEZJTEUgSS9PCnZvaWQgc2V0SW4oc3RyIHMpIHsgZnJlb3BlbihzLmNfc3RyKCksInIiLHN0ZGluKTsgfQp2b2lkIHNldE91dChzdHIgcykgeyBmcmVvcGVuKHMuY19zdHIoKSwidyIsc3Rkb3V0KTsgfQp2b2lkIHVuc3luY0lPKCkgeyBjaW4udGllKDApLT5zeW5jX3dpdGhfc3RkaW8oMCk7IH0Kdm9pZCBzZXRJTyhzdHIgcyA9ICIiKSB7Cgl1bnN5bmNJTygpOwoJLy8gY2luLmV4Y2VwdGlvbnMoY2luLmZhaWxiaXQpOyAKCS8vIHRocm93cyBleGNlcHRpb24gd2hlbiBkbyBzbXRoIGlsbGVnYWwKCS8vIGV4LiB0cnkgdG8gcmVhZCBsZXR0ZXIgaW50byBpbnQKCWlmIChzeihzKSkgeyBzZXRJbihzKyIuaW4iKSwgc2V0T3V0KHMrIi5vdXQiKTsgfSAvLyBmb3IgVVNBQ08KfQoKLyoqCiAqIERlc2NyaXB0aW9uOiAxRCByYW5nZSBpbmNyZW1lbnQgYW5kIHN1bSBxdWVyeS4KICogU291cmNlOiBVU0FDTyBDb3VudGluZyBIYXliYWxlcwogKiBWZXJpZmljYXRpb246IFNQT0ogSG9ycmlibGUKICovCgp0ZW1wbGF0ZTxjbGFzcyBULCBpbnQgU1o+IHN0cnVjdCBMYXp5U2VnIHsgCglzdGF0aWNfYXNzZXJ0KHBjdChTWikgPT0gMSk7IC8vIFNaIG11c3QgYmUgcG93ZXIgb2YgMgoJY29uc3QgVCBJRCA9IHt7MCwwfX07IAoJVCBjb21iKFQgYSwgVCBiKSB7IHJldHVybiB7YVswXStiWzBdLGFbMV0rYlsxXX07IH0KCVQgc2VnWzIqU1pdOwoJaW50IGxhenlbMipTWl07IAoJTGF6eVNlZygpIHsgCgkJRjBSKGksMipTWikgc2VnW2ldID0gSUQ7IAoJfQoJdm9pZCBwdXNoKGludCBpbmQsIGludCBMLCBpbnQgUikgeyAvLy8gbW9kaWZ5IHZhbHVlcyBmb3IgY3VycmVudCBub2RlCgkJaWYgKCFsYXp5W2luZF0pIHJldHVybjsKCQlzd2FwKHNlZ1tpbmRdWzBdLHNlZ1tpbmRdWzFdKTsKCQkvLyBzZWdbaW5kXSArPSAoUi1MKzEpKmxhenlbaW5kXTsgLy8gZGVwZW5kZW50IG9uIG9wZXJhdGlvbgoJCWlmIChMICE9IFIpIEYwUihpLDIpIGxhenlbMippbmQraV0gXj0gbGF6eVtpbmRdOyAvLy8gcHJvcCB0byBjaGlsZHJlbgoJCWxhenlbaW5kXSA9IDA7IAoJfSAvLyByZWNhbGMgdmFsdWVzIGZvciBjdXJyZW50IG5vZGUKCXZvaWQgcHVsbChpbnQgaW5kKSB7IHNlZ1tpbmRdID0gY29tYihzZWdbMippbmRdLHNlZ1syKmluZCsxXSk7IH0KCXZvaWQgYnVpbGQoKSB7IFJPRihpLDEsU1opIHB1bGwoaSk7IH0KCXZvaWQgdXBkKGludCBsbyxpbnQgaGksaW50IGluZD0xLGludCBMPTAsIGludCBSPVNaLTEpIHsKCQlwdXNoKGluZCxMLFIpOyBpZiAoaGkgPCBMIHx8IFIgPCBsbykgcmV0dXJuOwoJCWlmIChsbyA8PSBMICYmIFIgPD0gaGkpIHsgCgkJCWxhenlbaW5kXSA9IDE7IHB1c2goaW5kLEwsUik7IHJldHVybjsgfQoJCWludCBNID0gKEwrUikvMjsgCgkJdXBkKGxvLGhpLDIqaW5kLEwsTSk7IAoJCXVwZChsbyxoaSwyKmluZCsxLE0rMSxSKTsgCgkJcHVsbChpbmQpOwoJfQoJVCBxdWVyeShpbnQgbG8sIGludCBoaSwgaW50IGluZD0xLCBpbnQgTD0wLCBpbnQgUj1TWi0xKSB7CgkJcHVzaChpbmQsTCxSKTsgaWYgKGxvID4gUiB8fCBMID4gaGkpIHJldHVybiBJRDsKCQlpZiAobG8gPD0gTCAmJiBSIDw9IGhpKSByZXR1cm4gc2VnW2luZF07CgkJaW50IE0gPSAoTCtSKS8yOyAKCQlyZXR1cm4gY29tYihxdWVyeShsbyxoaSwyKmluZCxMLE0pLHF1ZXJ5KGxvLGhpLDIqaW5kKzEsTSsxLFIpKTsKCX0KfTsKCkxhenlTZWc8QVI8aW50LDI+LDE8PDE2PiBMOwoKLyoqCiAqIERlc2NyaXB0aW9uOiBIZWF2eS1MaWdodCBEZWNvbXBvc2l0aW9uLCBhZGQgdmFsIHRvIHZlcnRzIAogCSogYW5kIHF1ZXJ5IHN1bSBpbiBwYXRoL3N1YnRyZWUuCiAqIFRpbWU6IGFueSB0cmVlIHBhdGggaXMgc3BsaXQgaW50byAkTyhcbG9nIE4pJCBwYXJ0cwogKiBTb3VyY2U6IGh0dHA6Ly9jLi4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi5zLmNvbS9ibG9nL2VudHJ5LzIyMDcyLCBodHRwczovL2MuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLnMuY29tL2Jsb2cvZW50cnkvNTMxNzAKICogVmVyaWZpY2F0aW9uOiAqCiAqLwoKLy8gI2luY2x1ZGUgIi4uLy4uL2RhdGEtc3RydWN0dXJlcy8xRCBSYW5nZSBRdWVyaWVzICg5LjIpL0xhenlTZWcgKDE1LjIpLmgiCgpjb25zdCBpbnQgU1ogPSA1MDAwNTsKCnZpIGFkaltTWl07CmludCBwYXJbU1pdLCByb290W1NaXSwgZGVwdGhbU1pdLCBzeltTWl0sIHRpOwppbnQgcG9zW1NaXTsgdmkgcnBvczsgLy8gcnBvcyBub3QgdXNlZCwgYnV0IGNvdWxkIGJlIHVzZWZ1bApsbCBzdG9yW01YXTsKCnRlbXBsYXRlPGludCBTWiwgYm9vbCBWQUxTX0lOX0VER0VTPiBzdHJ1Y3QgSExEIHsgCgl2b2lkIGFlKGludCB4LCBpbnQgeSkgeyBhZGpbeF0ucGIoeSksIGFkalt5XS5wYih4KTsgfQoJdm9pZCBkZnNTeihpbnQgeCkgeyAKCQlzelt4XSA9IDE7IAoJCXRyYXYoeSxhZGpbeF0pIHsKCQkJcGFyW3ldID0geDsgZGVwdGhbeV0gPSBkZXB0aFt4XSsxOwoJCQlhZGpbeV0uZXJhc2UoZmluZChhbGwoYWRqW3ldKSx4KSk7IC8vIHJlbW92ZSBwYXJlbnQgZnJvbSBhZGogbGlzdAoJCQlkZnNTeih5KTsgc3pbeF0gKz0gc3pbeV07CgkJCWlmIChzelt5XSA+IHN6W2Fkalt4XVswXV0pIHN3YXAoeSxhZGpbeF1bMF0pOwoJCX0KCX0KCXZvaWQgZGZzSGxkKGludCB4KSB7CgkJcG9zW3hdID0gdGkrKzsgcnBvcy5wYih4KTsKCQl0cmF2KHksYWRqW3hdKSB7CgkJCXJvb3RbeV0gPSAoeSA9PSBhZGpbeF1bMF0gPyByb290W3hdIDogeSk7CgkJCWRmc0hsZCh5KTsgfQoJfQoJdm9pZCBpbml0KCkgewoJCWludCBSID0gMDsKCQlwYXJbUl0gPSBkZXB0aFtSXSA9IHRpID0gMDsgZGZzU3ooUik7IAoJCXJvb3RbUl0gPSBSOyBkZnNIbGQoUik7IAoJfQoJaW50IGxjYShpbnQgeCwgaW50IHkpIHsKCQlmb3IgKDsgcm9vdFt4XSAhPSByb290W3ldOyB5ID0gcGFyW3Jvb3RbeV1dKQoJCQlpZiAoZGVwdGhbcm9vdFt4XV0gPiBkZXB0aFtyb290W3ldXSkgc3dhcCh4LHkpOwoJCXJldHVybiBkZXB0aFt4XSA8IGRlcHRoW3ldID8geCA6IHk7Cgl9CgkvLy8gaW50IGRpc3QoaW50IHgsIGludCB5KSB7IC8vICMgZWRnZXMgb24gcGF0aAoJLy8vIAlyZXR1cm4gZGVwdGhbeF0rZGVwdGhbeV0tMipkZXB0aFtsY2EoeCx5KV07IH0KCS8vIExhenlTZWc8bGwsU1o+IHRyZWU7IC8vIHNlZ3RyZWUgZm9yIHN1bQoJLy8gdGVtcGxhdGUgPGNsYXNzIEJpbmFyeU9wPgoJLy8gdm9pZCBwcm9jZXNzUGF0aChpbnQgeCwgaW50IHksIEJpbmFyeU9wIG9wKSB7CgkvLyAJZm9yICg7IHJvb3RbeF0gIT0gcm9vdFt5XTsgeSA9IHBhcltyb290W3ldXSkgewoJLy8gCQlpZiAoZGVwdGhbcm9vdFt4XV0gPiBkZXB0aFtyb290W3ldXSkgc3dhcCh4LHkpOwoJLy8gCQlvcChwb3Nbcm9vdFt5XV0scG9zW3ldKTsgfQoJLy8gCWlmIChkZXB0aFt4XSA+IGRlcHRoW3ldKSBzd2FwKHgseSk7CgkvLyAJb3AocG9zW3hdK1ZBTFNfSU5fRURHRVMscG9zW3ldKTsgCgkvLyB9CgkvLyB2b2lkIG1vZGlmeVBhdGgoaW50IHgsIGludCB5LCBpbnQgdikgeyAKCS8vIAlwcm9jZXNzUGF0aCh4LHksW3RoaXMsJnZdKGludCBsLCBpbnQgcikgeyAKCS8vIAkJdHJlZS51cGQobCxyLHYpOyB9KTsgfQoJLy8gbGwgcXVlcnlQYXRoKGludCB4LCBpbnQgeSkgeyAKCS8vIAlsbCByZXMgPSAwOyBwcm9jZXNzUGF0aCh4LHksW3RoaXMsJnJlc10oaW50IGwsIGludCByKSB7IAoJLy8gCQlyZXMgKz0gdHJlZS5xdWVyeShsLHIpOyB9KTsKCS8vIAlyZXR1cm4gcmVzOyB9CgkvLyB2b2lkIG1vZGlmeVN1YnRyZWUoaW50IHgsIGludCB2KSB7IAoJLy8gCXRyZWUudXBkKHBvc1t4XStWQUxTX0lOX0VER0VTLHBvc1t4XStzelt4XS0xLHYpOyB9Cn07CgpsbCBzcShpbnQgeCkgewoJbGwgbnVtID0gTC5xdWVyeShwb3NbeF0scG9zW3hdK3N6W3hdLTEpWzFdOwoJcmV0dXJuIG51bSoobnVtLTEpLzI7Cn0KCkhMRDw1MDAwNSwwPiBIOwppbnQgTixRLEFbTVhdOwovLyB2aSBjaGlsZFtNWF07Cgp2b2lkIGZsaXAoaW50IHgpIHsKCWZvciAoaW50IHkgPSB4OyAwICE9IHJvb3RbeV07IHkgPSBwYXJbcm9vdFt5XV0pIHsKCQlpbnQgcCA9IHBhcltyb290W3ldXTsKCQlzdG9yW3BdIC09IHNxKHJvb3RbeV0pOwoJfQoJZm9yIChpbnQgeSA9IHg7IDsgeSA9IHBhcltyb290W3ldXSkgewoJCWlmIChyb290W3ldID09IDApIHsKCQkJTC51cGQocG9zWzBdLHBvc1t5XSk7IAoJCQlicmVhazsKCQl9IGVsc2UgewoJCQlMLnVwZChwb3Nbcm9vdFt5XV0scG9zW3ldKTsgCgkJfQoJfQoJZm9yIChpbnQgeSA9IHg7IDAgIT0gcm9vdFt5XTsgeSA9IHBhcltyb290W3ldXSkgewoJCWludCBwID0gcGFyW3Jvb3RbeV1dOwoJCXN0b3JbcF0gKz0gc3Eocm9vdFt5XSk7Cgl9Cn0KCmludCBtYWluKCkgewoJc2V0SU8oKTsgcmUoTixRKTsKCUYwUihpLE4pIHJlKEFbaV0pOwoJRjBSKGksTi0xKSB7CgkJaW50IHUsdjsgcmUodSx2KTsgdS0tLHYtLTsKCQlILmFlKHUsdik7Cgl9CglILmluaXQoKTsKCUYwUihpLE4pIHsKCQlMLnNlZ1soMTw8MTYpK3Bvc1tpXV1bQVtpXV0gPSAxOwoJfSAKCUwuYnVpbGQoKTsKCUYwUihpLE4pIHsKCQlGT1IoaiwxLHN6KGFkaltpXSkpIHN0b3JbaV0gKz0gc3EoYWRqW2ldW2pdKTsKCX0KCS8vIEYwUihpLE4pIGRiZyhpLHNxKGkpKTsKCUYwUihpLFEpIHsKCQlpbnQgbyx4OyByZShvLHgpOyB4IC0tOwoJCWlmIChvID09IDEpIHsKCQkJZmxpcCh4KTsKCQl9IGVsc2UgewoJCQlsbCBhbnMgPSBzcSh4KS1zdG9yW3hdOwoJCQlpZiAoc3ooYWRqW3hdKSkgYW5zIC09IHNxKGFkalt4XVswXSk7CgkJCXBzKGFucyk7CgkJfQoJfQoJLy8gSExEPyBibG9jayB0cmVlPwoKCS8vIHlvdSBzaG91bGQgYWN0dWFsbHkgcmVhZCB0aGUgc3R1ZmYgYXQgdGhlIGJvdHRvbQp9CgovKiBzdHVmZiB5b3Ugc2hvdWxkIGxvb2sgZm9yCgkqIGludCBvdmVyZmxvdywgYXJyYXkgYm91bmRzCgkqIHNwZWNpYWwgY2FzZXMgKG49MT8pCgkqIGRvIHNtdGggaW5zdGVhZCBvZiBub3RoaW5nIGFuZCBzdGF5IG9yZ2FuaXplZAoJKiBXUklURSBTVFVGRiBET1dOCgkqIERPTidUIEdFVCBTVFVDSyBPTiBPTkUgQVBQUk9BQ0gKKi8=