- /***********Template Starts Here***********/ 
- #include <bits/stdc++.h> 
-   
- #define pb push_back 
- #define nl puts ("") 
- #define sp printf ( " " ) 
- #define phl printf ( "hello\n" ) 
- #define ff first 
- #define ss second 
- #define POPCOUNT __builtin_popcountll 
- #define RIGHTMOST __builtin_ctzll 
- #define LEFTMOST(x) (63-__builtin_clzll((x))) 
- #define MP make_pair 
- #define FOR(i,x,y) for(vlong i = (x) ; i <= (y) ; ++i) 
- #define ROF(i,x,y) for(vlong i = (y) ; i >= (x) ; --i) 
- #define CLR(x,y) memset(x,y,sizeof(x)) 
- #define UNIQUE(V) (V).erase(unique((V).begin(),(V).end()),(V).end()) 
- #define MIN(a,b) ((a)<(b)?(a):(b)) 
- #define MAX(a,b) ((a)>(b)?(a):(b)) 
- #define NUMDIGIT(x,y) (((vlong)(log10((x))/log10((y))))+1) 
- #define SQ(x) ((x)*(x)) 
- #define ABS(x) ((x)<0?-(x):(x)) 
- #define FABS(x) ((x)+eps<0?-(x):(x)) 
- #define ALL(x) (x).begin(),(x).end() 
- #define LCM(x,y) (((x)/gcd((x),(y)))*(y)) 
- #define SZ(x) ((vlong)(x).size()) 
- #define NORM(x) if(x>=mod)x-=mod; 
-   
- using namespace std; 
-   
- typedef long long vlong; 
- typedef unsigned long long uvlong; 
- typedef pair < int, int > pii; 
- typedef pair < vlong, vlong > pll; 
- typedef vector<pii> vii; 
- typedef vector<int> vi; 
-   
- const vlong inf = 2147383647; 
-   
- /***********Template Ends Here***********/ 
-   
- #define LCANODE 100010 
- #define LCADEPTH 20 
- vi adj[LCANODE]; 
- struct LCA{ 
-     private: 
-     int tab[LCANODE][LCADEPTH], lev[LCANODE], vis[LCANODE], q[LCANODE], cc, N, M, root; 
-   
-     public: 
-     int par[LCANODE]; 
-   
-     private: 
-     void bfs ( int s ) { 
-         vis[s] = cc; 
-         lev[s] = 0; 
-         par[s] = -1; ///Set par[root] = -1 
-   
-         int qh = 0, qt = 0; 
-         q[qt++] = s; 
-         int t; 
-         while ( qh < qt ) { 
-             s = q[qh++]; 
-             FOR(i,0,SZ(adj[s])-1){ 
-                 t = adj[s][i]; 
-                 if ( vis[t] != cc ) { 
-                     par[t] = s; 
-                     vis[t] = cc; 
-                     lev[t] = lev[s] + 1; 
-                     q[qt++] = t; 
-                 } 
-             } 
-         } 
-     } 
-   
-     void calculate (){ 
-         int i,j,p; 
-         for (i=0;i<=N;i++){ 
-            tab[i][0]=par[i]; 
-         } 
-   
-         for(i=1;i<=M;i++){ 
-             for(j=0;j<=N;j++){ 
-                 p=tab[j][i-1]; 
-                 if(p==-1) tab[j][i]=-1; 
-                 else tab[j][i]=tab[p][i-1]; 
-             } 
-         } 
-     } 
-   
-     public: 
-     void clear () { 
-         cc++; 
-         FOR(i,0,N) adj[i].clear(); 
-     } 
-   
-     LCA() { 
-         cc = 1; 
-     } 
-   
-     void setVar ( int n, int r ) { 
-         N = n; 
-   
-         M = 0; 
-         int temp = n+1; 
-         while ( temp ) { 
-             M++; 
-             temp /= 2; 
-         } 
-         root = r; 
-         clear(); 
-     } 
-     void precal () { 
-         bfs ( root ); 
-         calculate(); 
-     } 
-     int findLCA(int s,int t){ 
-         int dif,pos,i; 
-         if(lev[s]!=lev[t] ) { 
-             if(lev[s]>lev[t]) swap( s, t ); 
-             dif=lev[t]-lev[s]; 
-             while(dif){ 
-                 pos=RIGHTMOST(dif); 
-                 t=tab[t][pos]; 
-                 dif-=1<<pos; 
-             } 
-         } 
-         if (s==t)return s; 
-         for(i=M;i>=0;i--){ 
-             if(tab[s][i]!=tab[t][i]){ 
-                 s=tab[s][i]; 
-                 t=tab[t][i]; 
-             } 
-         } 
-         return tab[s][0]; 
-     } 
- }lca; 
-   
- int child[100010]; 
- int pretrav[100010], pre = 0; 
- int preStart[100010]; 
- void dfs ( int s, int p ) { 
-     child[s] = 1; 
-     preStart[s] = pre; 
-     pretrav[pre++] = s; 
-   
-     FOR(i,0,SZ(adj[s])-1){ 
-         int t = adj[s][i]; 
-         if ( t == p ) continue; 
-         dfs ( t, s ); 
-         child[s] += child[t]; 
-     } 
- } 
-   
- int color[100010], arr[11][100010]; 
-   
- void dfs2 ( int s, int p, int d, int c ) { 
-     arr[c][s] = d; 
-   
-     FOR(i,0,SZ(adj[s])-1){ 
-         int t = adj[s][i]; 
-         if ( t == p ) continue; 
-         int cost = 0; 
-         if ( color[t] == c ) cost = 1; 
-   
-         dfs2 ( t, s, d + cost, c ); 
-     } 
- } 
-   
- struct node { 
-     int val; 
-     int lazy; 
- }tn[11][4*100000]; 
-   
- void build ( int col, int t, int b, int e ) { 
-     int m = ( b + e ) / 2; 
-     int u = t * 2; 
-     int v = u + 1; 
-   
-     tn[col][t].lazy = 0; ///lazyClear(); 
-   
-     if ( b == e ) { 
-         tn[col][t].val = arr[col][pretrav[b]]; 
-         return; 
-     } 
-   
-     build( col, u, b, m ); 
-     build( col, v, m + 1, e ); 
- } 
-   
- int qb, qe, qv; 
- void lazyPropagate ( node &p, node &u, node &v ) { 
-     u.lazy += p.lazy; 
-     v.lazy += p.lazy; 
- } 
-   
- void update ( int col, int t, int b, int e ) { 
-     int m = ( b + e ) / 2; 
-     int u = t * 2; 
-     int v = u + 1; 
-   
-     if ( qb <= b && e <= qe ) { 
-         tn[col][t].lazy += qv;///lazyUpdate(); 
-         tn[col][t].val += tn[col][t].lazy;///calculate(); 
-         if ( b != e ) lazyPropagate ( tn[col][t], tn[col][u], tn[col][v] ); 
-         tn[col][t].lazy = 0; ///LazyClear 
-         return; 
-     } 
-     if ( qe < b || e < qb ) { 
-         tn[col][t].val += tn[col][t].lazy;///calculate(); 
-         if ( b != e ) lazyPropagate ( tn[col][t], tn[col][u], tn[col][v] ); 
-         tn[col][t].lazy = 0; ///LazyClear 
-         return; 
-     } 
-   
-     lazyPropagate ( tn[col][t], tn[col][u], tn[col][v] ); 
-     tn[col][t].lazy = 0; ///LazyClear 
-   
-     update( col, u, b, m ); 
-     update( col, v, m + 1, e ); 
-   
- } 
-   
- int qvv[11]; 
-   
- void query ( int t, int b, int e ) { 
-     int m = ( b + e ) / 2; 
-     int u = t * 2; 
-     int v = u + 1; 
-   
-     if ( qb <= b && e <= qe ) { 
-         FOR(i,1,10) tn[i][t].val += tn[i][t].lazy;///calculate(); 
-         if ( b != e ) { 
-             FOR(i,1,10) lazyPropagate ( tn[i][t], tn[i][u], tn[i][v] ); 
-         } 
-         FOR(i,1,10) tn[i][t].lazy = 0; ///LazyClear 
-         FOR(i,1,10) qvv[i] = tn[i][t].val; 
-         return; 
-     } 
-     if ( qe < b || e < qb ) { 
-         FOR(i,1,10) tn[i][t].val += tn[i][t].lazy;///calculate(); 
-         if ( b != e ) { 
-             FOR(i,1,10) lazyPropagate ( tn[i][t], tn[i][u], tn[i][v] ); 
-         } 
-         FOR(i,1,10) tn[i][t].lazy = 0; ///LazyClear 
-         return; 
-     } 
-   
-     FOR(i,1,10) lazyPropagate ( tn[i][t], tn[i][u], tn[i][v] ); 
-     FOR(i,1,10) tn[i][t].lazy = 0; ///LazyClear 
-   
-     query( u, b, m ); 
-     query( v, m + 1, e ); 
-   
- } 
-   
- int main () { 
-   
-     int kase; 
-     scanf ( "%d", &kase ); 
-   
-     while ( kase-- ) { 
-         int n, m; 
-         scanf ( "%d %d", &n, &m ); 
-   
-         lca.setVar( n, 0 ); 
-   
-         CLR(color,0); 
-         FOR(i,1,n){ 
-             int c; 
-             scanf ( "%d", &c ); 
-             color[i] = c; ///Set color 
-         } 
-   
-         FOR(i,0,n-2){ 
-             int a, b; 
-             scanf ( "%d %d", &a, &b ); 
-             adj[a].pb ( b ); 
-             adj[b].pb ( a ); 
-         } 
-         adj[0].pb ( 1 ); ///Dummy node 
-   
-         lca.precal(); 
-   
-         pre = 0; 
-         dfs ( 0, -1 ); ///Calculate child, starting position in pre-traversal 
-   
-         ///Calculate distance in each color tree 
-         FOR(i,1,10){ 
-             dfs2 ( 0, -1, 0, i ); 
-         } 
-   
-   
-         ///Preparations complete. Start segment tree 
-         FOR(i,1,10) { 
-             build ( i, 1, 0, n ); 
-         } 
-   
-         while ( m-- ) { 
-             int t; 
-             scanf ( "%d", &t ); 
-   
-             if ( t == 0 ) { 
-                 int u, c; 
-                 scanf ( "%d %d", &u, &c ); 
-   
-                 ///Change color from color[u] to c 
-                 int p = color[u]; 
-                 ///Update the subtree of u of color p with -1 
-                 qb = preStart[u]; qe = qb + child[u] - 1; qv = -1; 
-                 update ( p, 1, 0, n ); 
-   
-                 ///Update the subtree of u of color c with +1 
-                 qv = 1; 
-                 update ( c, 1, 0, n ); 
-                 color[u] = c; 
-             } 
-             else { 
-                 int u, v; 
-                 scanf ( "%d %d", &u, &v ); 
-   
-                 ///Find distance in each color tree 
-                 int res = 0; 
-   
-                 int tres[11]; 
-                 CLR(tres,0); 
-   
-                 qb = preStart[u]; qe = qb; 
-                 query( 1, 0, n ); 
-   
-                 FOR(i,1,10) tres[i] = qvv[i]; 
-   
-   
-                 qb = preStart[v]; qe = qb; 
-                 query( 1, 0, n ); 
-   
-                 FOR(i,1,10) tres[i] += qvv[i]; 
-   
-                 int par = lca.findLCA( u, v ); 
-   
-                 qb = preStart[par]; qe = qb; 
-                 query( 1, 0, n ); 
-                 FOR(i,1,10) tres[i] -= 2 * qvv[i]; 
-   
-                 FOR(i,1,10){ 
-                     int col = color[par]; 
-                     if ( col == i ) tres[i]++; 
-                 } 
-   
-                 FOR(i,1,10) res = MAX(res,tres[i]); 
-   
-                 printf ( "%d\n", res ); 
-             } 
-         } 
-     } 
-   
-     return 0; 
- } 
-   
				LyoqKioqKioqKioqVGVtcGxhdGUgU3RhcnRzIEhlcmUqKioqKioqKioqKi8KI2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CgojZGVmaW5lIHBiIHB1c2hfYmFjawojZGVmaW5lIG5sIHB1dHMgKCIiKQojZGVmaW5lIHNwIHByaW50ZiAoICIgIiApCiNkZWZpbmUgcGhsIHByaW50ZiAoICJoZWxsb1xuIiApCiNkZWZpbmUgZmYgZmlyc3QKI2RlZmluZSBzcyBzZWNvbmQKI2RlZmluZSBQT1BDT1VOVCBfX2J1aWx0aW5fcG9wY291bnRsbAojZGVmaW5lIFJJR0hUTU9TVCBfX2J1aWx0aW5fY3R6bGwKI2RlZmluZSBMRUZUTU9TVCh4KSAoNjMtX19idWlsdGluX2NsemxsKCh4KSkpCiNkZWZpbmUgTVAgbWFrZV9wYWlyCiNkZWZpbmUgRk9SKGkseCx5KSBmb3IodmxvbmcgaSA9ICh4KSA7IGkgPD0gKHkpIDsgKytpKQojZGVmaW5lIFJPRihpLHgseSkgZm9yKHZsb25nIGkgPSAoeSkgOyBpID49ICh4KSA7IC0taSkKI2RlZmluZSBDTFIoeCx5KSBtZW1zZXQoeCx5LHNpemVvZih4KSkKI2RlZmluZSBVTklRVUUoVikgKFYpLmVyYXNlKHVuaXF1ZSgoVikuYmVnaW4oKSwoVikuZW5kKCkpLChWKS5lbmQoKSkKI2RlZmluZSBNSU4oYSxiKSAoKGEpPChiKT8oYSk6KGIpKQojZGVmaW5lIE1BWChhLGIpICgoYSk+KGIpPyhhKTooYikpCiNkZWZpbmUgTlVNRElHSVQoeCx5KSAoKCh2bG9uZykobG9nMTAoKHgpKS9sb2cxMCgoeSkpKSkrMSkKI2RlZmluZSBTUSh4KSAoKHgpKih4KSkKI2RlZmluZSBBQlMoeCkgKCh4KTwwPy0oeCk6KHgpKQojZGVmaW5lIEZBQlMoeCkgKCh4KStlcHM8MD8tKHgpOih4KSkKI2RlZmluZSBBTEwoeCkgKHgpLmJlZ2luKCksKHgpLmVuZCgpCiNkZWZpbmUgTENNKHgseSkgKCgoeCkvZ2NkKCh4KSwoeSkpKSooeSkpCiNkZWZpbmUgU1ooeCkgKCh2bG9uZykoeCkuc2l6ZSgpKQojZGVmaW5lIE5PUk0oeCkgaWYoeD49bW9kKXgtPW1vZDsKCnVzaW5nIG5hbWVzcGFjZSBzdGQ7Cgp0eXBlZGVmIGxvbmcgbG9uZyB2bG9uZzsKdHlwZWRlZiB1bnNpZ25lZCBsb25nIGxvbmcgdXZsb25nOwp0eXBlZGVmIHBhaXIgPCBpbnQsIGludCA+IHBpaTsKdHlwZWRlZiBwYWlyIDwgdmxvbmcsIHZsb25nID4gcGxsOwp0eXBlZGVmIHZlY3RvcjxwaWk+IHZpaTsKdHlwZWRlZiB2ZWN0b3I8aW50PiB2aTsKCmNvbnN0IHZsb25nIGluZiA9IDIxNDczODM2NDc7CgovKioqKioqKioqKipUZW1wbGF0ZSBFbmRzIEhlcmUqKioqKioqKioqKi8KCiNkZWZpbmUgTENBTk9ERSAxMDAwMTAKI2RlZmluZSBMQ0FERVBUSCAyMAp2aSBhZGpbTENBTk9ERV07CnN0cnVjdCBMQ0F7CiAgICBwcml2YXRlOgogICAgaW50IHRhYltMQ0FOT0RFXVtMQ0FERVBUSF0sIGxldltMQ0FOT0RFXSwgdmlzW0xDQU5PREVdLCBxW0xDQU5PREVdLCBjYywgTiwgTSwgcm9vdDsKCiAgICBwdWJsaWM6CiAgICBpbnQgcGFyW0xDQU5PREVdOwoKICAgIHByaXZhdGU6CiAgICB2b2lkIGJmcyAoIGludCBzICkgewogICAgICAgIHZpc1tzXSA9IGNjOwogICAgICAgIGxldltzXSA9IDA7CiAgICAgICAgcGFyW3NdID0gLTE7IC8vL1NldCBwYXJbcm9vdF0gPSAtMQoKICAgICAgICBpbnQgcWggPSAwLCBxdCA9IDA7CiAgICAgICAgcVtxdCsrXSA9IHM7CiAgICAgICAgaW50IHQ7CiAgICAgICAgd2hpbGUgKCBxaCA8IHF0ICkgewogICAgICAgICAgICBzID0gcVtxaCsrXTsKICAgICAgICAgICAgRk9SKGksMCxTWihhZGpbc10pLTEpewogICAgICAgICAgICAgICAgdCA9IGFkaltzXVtpXTsKICAgICAgICAgICAgICAgIGlmICggdmlzW3RdICE9IGNjICkgewogICAgICAgICAgICAgICAgICAgIHBhclt0XSA9IHM7CiAgICAgICAgICAgICAgICAgICAgdmlzW3RdID0gY2M7CiAgICAgICAgICAgICAgICAgICAgbGV2W3RdID0gbGV2W3NdICsgMTsKICAgICAgICAgICAgICAgICAgICBxW3F0KytdID0gdDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICB2b2lkIGNhbGN1bGF0ZSAoKXsKICAgICAgICBpbnQgaSxqLHA7CiAgICAgICAgZm9yIChpPTA7aTw9TjtpKyspewogICAgICAgICAgIHRhYltpXVswXT1wYXJbaV07CiAgICAgICAgfQoKICAgICAgICBmb3IoaT0xO2k8PU07aSsrKXsKICAgICAgICAgICAgZm9yKGo9MDtqPD1OO2orKyl7CiAgICAgICAgICAgICAgICBwPXRhYltqXVtpLTFdOwogICAgICAgICAgICAgICAgaWYocD09LTEpIHRhYltqXVtpXT0tMTsKICAgICAgICAgICAgICAgIGVsc2UgdGFiW2pdW2ldPXRhYltwXVtpLTFdOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIHB1YmxpYzoKICAgIHZvaWQgY2xlYXIgKCkgewogICAgICAgIGNjKys7CiAgICAgICAgRk9SKGksMCxOKSBhZGpbaV0uY2xlYXIoKTsKICAgIH0KCiAgICBMQ0EoKSB7CiAgICAgICAgY2MgPSAxOwogICAgfQoKICAgIHZvaWQgc2V0VmFyICggaW50IG4sIGludCByICkgewogICAgICAgIE4gPSBuOwoKICAgICAgICBNID0gMDsKICAgICAgICBpbnQgdGVtcCA9IG4rMTsKICAgICAgICB3aGlsZSAoIHRlbXAgKSB7CiAgICAgICAgICAgIE0rKzsKICAgICAgICAgICAgdGVtcCAvPSAyOwogICAgICAgIH0KICAgICAgICByb290ID0gcjsKICAgICAgICBjbGVhcigpOwogICAgfQogICAgdm9pZCBwcmVjYWwgKCkgewogICAgICAgIGJmcyAoIHJvb3QgKTsKICAgICAgICBjYWxjdWxhdGUoKTsKICAgIH0KICAgIGludCBmaW5kTENBKGludCBzLGludCB0KXsKICAgICAgICBpbnQgZGlmLHBvcyxpOwogICAgICAgIGlmKGxldltzXSE9bGV2W3RdICkgewogICAgICAgICAgICBpZihsZXZbc10+bGV2W3RdKSBzd2FwKCBzLCB0ICk7CiAgICAgICAgICAgIGRpZj1sZXZbdF0tbGV2W3NdOwogICAgICAgICAgICB3aGlsZShkaWYpewogICAgICAgICAgICAgICAgcG9zPVJJR0hUTU9TVChkaWYpOwogICAgICAgICAgICAgICAgdD10YWJbdF1bcG9zXTsKICAgICAgICAgICAgICAgIGRpZi09MTw8cG9zOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChzPT10KXJldHVybiBzOwogICAgICAgIGZvcihpPU07aT49MDtpLS0pewogICAgICAgICAgICBpZih0YWJbc11baV0hPXRhYlt0XVtpXSl7CiAgICAgICAgICAgICAgICBzPXRhYltzXVtpXTsKICAgICAgICAgICAgICAgIHQ9dGFiW3RdW2ldOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiB0YWJbc11bMF07CiAgICB9Cn1sY2E7CgppbnQgY2hpbGRbMTAwMDEwXTsKaW50IHByZXRyYXZbMTAwMDEwXSwgcHJlID0gMDsKaW50IHByZVN0YXJ0WzEwMDAxMF07CnZvaWQgZGZzICggaW50IHMsIGludCBwICkgewogICAgY2hpbGRbc10gPSAxOwogICAgcHJlU3RhcnRbc10gPSBwcmU7CiAgICBwcmV0cmF2W3ByZSsrXSA9IHM7CgogICAgRk9SKGksMCxTWihhZGpbc10pLTEpewogICAgICAgIGludCB0ID0gYWRqW3NdW2ldOwogICAgICAgIGlmICggdCA9PSBwICkgY29udGludWU7CiAgICAgICAgZGZzICggdCwgcyApOwogICAgICAgIGNoaWxkW3NdICs9IGNoaWxkW3RdOwogICAgfQp9CgppbnQgY29sb3JbMTAwMDEwXSwgYXJyWzExXVsxMDAwMTBdOwoKdm9pZCBkZnMyICggaW50IHMsIGludCBwLCBpbnQgZCwgaW50IGMgKSB7CiAgICBhcnJbY11bc10gPSBkOwoKICAgIEZPUihpLDAsU1ooYWRqW3NdKS0xKXsKICAgICAgICBpbnQgdCA9IGFkaltzXVtpXTsKICAgICAgICBpZiAoIHQgPT0gcCApIGNvbnRpbnVlOwogICAgICAgIGludCBjb3N0ID0gMDsKICAgICAgICBpZiAoIGNvbG9yW3RdID09IGMgKSBjb3N0ID0gMTsKCiAgICAgICAgZGZzMiAoIHQsIHMsIGQgKyBjb3N0LCBjICk7CiAgICB9Cn0KCnN0cnVjdCBub2RlIHsKICAgIGludCB2YWw7CiAgICBpbnQgbGF6eTsKfXRuWzExXVs0KjEwMDAwMF07Cgp2b2lkIGJ1aWxkICggaW50IGNvbCwgaW50IHQsIGludCBiLCBpbnQgZSApIHsKICAgIGludCBtID0gKCBiICsgZSApIC8gMjsKICAgIGludCB1ID0gdCAqIDI7CiAgICBpbnQgdiA9IHUgKyAxOwoKICAgIHRuW2NvbF1bdF0ubGF6eSA9IDA7IC8vL2xhenlDbGVhcigpOwoKICAgIGlmICggYiA9PSBlICkgewogICAgICAgIHRuW2NvbF1bdF0udmFsID0gYXJyW2NvbF1bcHJldHJhdltiXV07CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGJ1aWxkKCBjb2wsIHUsIGIsIG0gKTsKICAgIGJ1aWxkKCBjb2wsIHYsIG0gKyAxLCBlICk7Cn0KCmludCBxYiwgcWUsIHF2Owp2b2lkIGxhenlQcm9wYWdhdGUgKCBub2RlICZwLCBub2RlICZ1LCBub2RlICZ2ICkgewogICAgdS5sYXp5ICs9IHAubGF6eTsKICAgIHYubGF6eSArPSBwLmxhenk7Cn0KCnZvaWQgdXBkYXRlICggaW50IGNvbCwgaW50IHQsIGludCBiLCBpbnQgZSApIHsKICAgIGludCBtID0gKCBiICsgZSApIC8gMjsKICAgIGludCB1ID0gdCAqIDI7CiAgICBpbnQgdiA9IHUgKyAxOwoKICAgIGlmICggcWIgPD0gYiAmJiBlIDw9IHFlICkgewogICAgICAgIHRuW2NvbF1bdF0ubGF6eSArPSBxdjsvLy9sYXp5VXBkYXRlKCk7CiAgICAgICAgdG5bY29sXVt0XS52YWwgKz0gdG5bY29sXVt0XS5sYXp5Oy8vL2NhbGN1bGF0ZSgpOwogICAgICAgIGlmICggYiAhPSBlICkgbGF6eVByb3BhZ2F0ZSAoIHRuW2NvbF1bdF0sIHRuW2NvbF1bdV0sIHRuW2NvbF1bdl0gKTsKICAgICAgICB0bltjb2xdW3RdLmxhenkgPSAwOyAvLy9MYXp5Q2xlYXIKICAgICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoIHFlIDwgYiB8fCBlIDwgcWIgKSB7CiAgICAgICAgdG5bY29sXVt0XS52YWwgKz0gdG5bY29sXVt0XS5sYXp5Oy8vL2NhbGN1bGF0ZSgpOwogICAgICAgIGlmICggYiAhPSBlICkgbGF6eVByb3BhZ2F0ZSAoIHRuW2NvbF1bdF0sIHRuW2NvbF1bdV0sIHRuW2NvbF1bdl0gKTsKICAgICAgICB0bltjb2xdW3RdLmxhenkgPSAwOyAvLy9MYXp5Q2xlYXIKICAgICAgICByZXR1cm47CiAgICB9CgogICAgbGF6eVByb3BhZ2F0ZSAoIHRuW2NvbF1bdF0sIHRuW2NvbF1bdV0sIHRuW2NvbF1bdl0gKTsKICAgIHRuW2NvbF1bdF0ubGF6eSA9IDA7IC8vL0xhenlDbGVhcgoKICAgIHVwZGF0ZSggY29sLCB1LCBiLCBtICk7CiAgICB1cGRhdGUoIGNvbCwgdiwgbSArIDEsIGUgKTsKCn0KCmludCBxdnZbMTFdOwoKdm9pZCBxdWVyeSAoIGludCB0LCBpbnQgYiwgaW50IGUgKSB7CiAgICBpbnQgbSA9ICggYiArIGUgKSAvIDI7CiAgICBpbnQgdSA9IHQgKiAyOwogICAgaW50IHYgPSB1ICsgMTsKCiAgICBpZiAoIHFiIDw9IGIgJiYgZSA8PSBxZSApIHsKICAgICAgICBGT1IoaSwxLDEwKSB0bltpXVt0XS52YWwgKz0gdG5baV1bdF0ubGF6eTsvLy9jYWxjdWxhdGUoKTsKICAgICAgICBpZiAoIGIgIT0gZSApIHsKICAgICAgICAgICAgRk9SKGksMSwxMCkgbGF6eVByb3BhZ2F0ZSAoIHRuW2ldW3RdLCB0bltpXVt1XSwgdG5baV1bdl0gKTsKICAgICAgICB9CiAgICAgICAgRk9SKGksMSwxMCkgdG5baV1bdF0ubGF6eSA9IDA7IC8vL0xhenlDbGVhcgogICAgICAgIEZPUihpLDEsMTApIHF2dltpXSA9IHRuW2ldW3RdLnZhbDsKICAgICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoIHFlIDwgYiB8fCBlIDwgcWIgKSB7CiAgICAgICAgRk9SKGksMSwxMCkgdG5baV1bdF0udmFsICs9IHRuW2ldW3RdLmxhenk7Ly8vY2FsY3VsYXRlKCk7CiAgICAgICAgaWYgKCBiICE9IGUgKSB7CiAgICAgICAgICAgIEZPUihpLDEsMTApIGxhenlQcm9wYWdhdGUgKCB0bltpXVt0XSwgdG5baV1bdV0sIHRuW2ldW3ZdICk7CiAgICAgICAgfQogICAgICAgIEZPUihpLDEsMTApIHRuW2ldW3RdLmxhenkgPSAwOyAvLy9MYXp5Q2xlYXIKICAgICAgICByZXR1cm47CiAgICB9CgogICAgRk9SKGksMSwxMCkgbGF6eVByb3BhZ2F0ZSAoIHRuW2ldW3RdLCB0bltpXVt1XSwgdG5baV1bdl0gKTsKICAgIEZPUihpLDEsMTApIHRuW2ldW3RdLmxhenkgPSAwOyAvLy9MYXp5Q2xlYXIKCiAgICBxdWVyeSggdSwgYiwgbSApOwogICAgcXVlcnkoIHYsIG0gKyAxLCBlICk7Cgp9CgppbnQgbWFpbiAoKSB7CgogICAgaW50IGthc2U7CiAgICBzY2FuZiAoICIlZCIsICZrYXNlICk7CgogICAgd2hpbGUgKCBrYXNlLS0gKSB7CiAgICAgICAgaW50IG4sIG07CiAgICAgICAgc2NhbmYgKCAiJWQgJWQiLCAmbiwgJm0gKTsKCiAgICAgICAgbGNhLnNldFZhciggbiwgMCApOwoKICAgICAgICBDTFIoY29sb3IsMCk7CiAgICAgICAgRk9SKGksMSxuKXsKICAgICAgICAgICAgaW50IGM7CiAgICAgICAgICAgIHNjYW5mICggIiVkIiwgJmMgKTsKICAgICAgICAgICAgY29sb3JbaV0gPSBjOyAvLy9TZXQgY29sb3IKICAgICAgICB9CgogICAgICAgIEZPUihpLDAsbi0yKXsKICAgICAgICAgICAgaW50IGEsIGI7CiAgICAgICAgICAgIHNjYW5mICggIiVkICVkIiwgJmEsICZiICk7CiAgICAgICAgICAgIGFkalthXS5wYiAoIGIgKTsKICAgICAgICAgICAgYWRqW2JdLnBiICggYSApOwogICAgICAgIH0KICAgICAgICBhZGpbMF0ucGIgKCAxICk7IC8vL0R1bW15IG5vZGUKCiAgICAgICAgbGNhLnByZWNhbCgpOwoKICAgICAgICBwcmUgPSAwOwogICAgICAgIGRmcyAoIDAsIC0xICk7IC8vL0NhbGN1bGF0ZSBjaGlsZCwgc3RhcnRpbmcgcG9zaXRpb24gaW4gcHJlLXRyYXZlcnNhbAoKICAgICAgICAvLy9DYWxjdWxhdGUgZGlzdGFuY2UgaW4gZWFjaCBjb2xvciB0cmVlCiAgICAgICAgRk9SKGksMSwxMCl7CiAgICAgICAgICAgIGRmczIgKCAwLCAtMSwgMCwgaSApOwogICAgICAgIH0KCgogICAgICAgIC8vL1ByZXBhcmF0aW9ucyBjb21wbGV0ZS4gU3RhcnQgc2VnbWVudCB0cmVlCiAgICAgICAgRk9SKGksMSwxMCkgewogICAgICAgICAgICBidWlsZCAoIGksIDEsIDAsIG4gKTsKICAgICAgICB9CgogICAgICAgIHdoaWxlICggbS0tICkgewogICAgICAgICAgICBpbnQgdDsKICAgICAgICAgICAgc2NhbmYgKCAiJWQiLCAmdCApOwoKICAgICAgICAgICAgaWYgKCB0ID09IDAgKSB7CiAgICAgICAgICAgICAgICBpbnQgdSwgYzsKICAgICAgICAgICAgICAgIHNjYW5mICggIiVkICVkIiwgJnUsICZjICk7CgogICAgICAgICAgICAgICAgLy8vQ2hhbmdlIGNvbG9yIGZyb20gY29sb3JbdV0gdG8gYwogICAgICAgICAgICAgICAgaW50IHAgPSBjb2xvclt1XTsKICAgICAgICAgICAgICAgIC8vL1VwZGF0ZSB0aGUgc3VidHJlZSBvZiB1IG9mIGNvbG9yIHAgd2l0aCAtMQogICAgICAgICAgICAgICAgcWIgPSBwcmVTdGFydFt1XTsgcWUgPSBxYiArIGNoaWxkW3VdIC0gMTsgcXYgPSAtMTsKICAgICAgICAgICAgICAgIHVwZGF0ZSAoIHAsIDEsIDAsIG4gKTsKCiAgICAgICAgICAgICAgICAvLy9VcGRhdGUgdGhlIHN1YnRyZWUgb2YgdSBvZiBjb2xvciBjIHdpdGggKzEKICAgICAgICAgICAgICAgIHF2ID0gMTsKICAgICAgICAgICAgICAgIHVwZGF0ZSAoIGMsIDEsIDAsIG4gKTsKICAgICAgICAgICAgICAgIGNvbG9yW3VdID0gYzsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIGludCB1LCB2OwogICAgICAgICAgICAgICAgc2NhbmYgKCAiJWQgJWQiLCAmdSwgJnYgKTsKCiAgICAgICAgICAgICAgICAvLy9GaW5kIGRpc3RhbmNlIGluIGVhY2ggY29sb3IgdHJlZQogICAgICAgICAgICAgICAgaW50IHJlcyA9IDA7CgogICAgICAgICAgICAgICAgaW50IHRyZXNbMTFdOwogICAgICAgICAgICAgICAgQ0xSKHRyZXMsMCk7CgogICAgICAgICAgICAgICAgcWIgPSBwcmVTdGFydFt1XTsgcWUgPSBxYjsKICAgICAgICAgICAgICAgIHF1ZXJ5KCAxLCAwLCBuICk7CgogICAgICAgICAgICAgICAgRk9SKGksMSwxMCkgdHJlc1tpXSA9IHF2dltpXTsKCgogICAgICAgICAgICAgICAgcWIgPSBwcmVTdGFydFt2XTsgcWUgPSBxYjsKICAgICAgICAgICAgICAgIHF1ZXJ5KCAxLCAwLCBuICk7CgogICAgICAgICAgICAgICAgRk9SKGksMSwxMCkgdHJlc1tpXSArPSBxdnZbaV07CgogICAgICAgICAgICAgICAgaW50IHBhciA9IGxjYS5maW5kTENBKCB1LCB2ICk7CgogICAgICAgICAgICAgICAgcWIgPSBwcmVTdGFydFtwYXJdOyBxZSA9IHFiOwogICAgICAgICAgICAgICAgcXVlcnkoIDEsIDAsIG4gKTsKICAgICAgICAgICAgICAgIEZPUihpLDEsMTApIHRyZXNbaV0gLT0gMiAqIHF2dltpXTsKCiAgICAgICAgICAgICAgICBGT1IoaSwxLDEwKXsKICAgICAgICAgICAgICAgICAgICBpbnQgY29sID0gY29sb3JbcGFyXTsKICAgICAgICAgICAgICAgICAgICBpZiAoIGNvbCA9PSBpICkgdHJlc1tpXSsrOwogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIEZPUihpLDEsMTApIHJlcyA9IE1BWChyZXMsdHJlc1tpXSk7CgogICAgICAgICAgICAgICAgcHJpbnRmICggIiVkXG4iLCByZXMgKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gMDsKfQo=