//#pragma GCC optimize("Ofast,unroll-loops")
//#pragma GCC target("avx2,tune=native")
#include <bits/stdc++.h>
using namespace std;
 
#define file "fakernum"
#define ff(i, a, b) for(auto i=(a); i<=(b); ++i)
#define ffr(i, b, a) for(auto i=(b); i>=(a); --i)
#define nl "\n"
#define ss " "
#define pb emplace_back
#define fi first
#define se second
#define sz(s) (int)s.size()
#define all(s) (s).begin(), (s).end()
#define ms(a,x) memset(a, x, sizeof (a))
#define cn continue
#define re exit(0)
 
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
 
const int mod=1e9+7;
const int maxn=1e5+15;
const ll inf=4e18;
 
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll ran(ll l, ll r)
{
    return uniform_int_distribution<ll> (l, r)(rng);
}
 
inline void rf(){
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr); cout.tie(nullptr);
    if(fopen(file".inp","r")){
        freopen(file".inp","r",stdin); freopen(file".out","w",stdout);
    }
}
 
template<typename T> inline void add(T &x, const T &y)
{
    x+=y;
    if(x>=mod) x-=mod;
    if(x<0) x+=mod;
}
 
template<typename T> inline bool maxi(T &a, T b)
{
    if(a>=b) return 0;
    a=b; return 1;
}
 
template<typename T> inline bool mini(T &a, T b)
{
    if(a<=b) return 0;
    a=b; return 1;
}
 
int n,q;
ll a[maxn];
vi g[maxn];
int par[maxn], h[maxn], heavy[maxn], head[maxn], st[maxn], ed[maxn], siz[maxn], timer_=0;
 
vll spev;
unordered_set<ll> spes;
 
inline string todecstr(ll x)
{
    if(x==0) return "0";
    string s; while(x){ s+=char('0'+(x%10)); x/=10; } reverse(all(s)); return s;
}
 
inline ll palsub(const string &s)
{
    int m=sz(s);
    ll ans=0;
    ff(c,0,m-1){
        int l=c, r=c;
        while(l>=0 && r<m && s[l]==s[r]){ ++ans; --l; ++r; }
    }
    ff(c,0,m-2){
        int l=c, r=c+1;
        while(l>=0 && r<m && s[l]==s[r]){ ++ans; --l; ++r; }
    }
    return ans;
}
 
inline bool valid(ll x)
{
    if(x<=0) return 0;
    string s=todecstr(x);
    int c3=0,c6=0;
    for(char c:s)
    {
        if(c=='3') ++c3;
        else if(c=='6') ++c6;
        else return 0;
    }
    if(c3!=c6) return 0;
    ll mau=1LL*sz(s)*(sz(s)+1)/2;
    ll tu=palsub(s);
    return tu*2>mau;
}
 
void gen(ll x)
{
    if(x>1e16) return;
    if(x!=0 && valid(x)) spev.pb(x);
    if(x==0){ gen(3); gen(6); }
    else
    {
        if(x<=1e15){ gen(x*10+3); gen(x*10+6); }
    }
}
 
int dfs1(int u, int p)
{
    par[u]=p; siz[u]=1; int mx=0; heavy[u]=0;
    for(int v:g[u]) if(v!=p)
    {
        h[v]=h[u]+1;
        int s=dfs1(v,u);
        siz[u]+=s;
        if(s>mx){ mx=s; heavy[u]=v; }
    }
    return siz[u];
}
void dfs2(int u, int hd)
{
    head[u]=hd; st[u]=++timer_;
    if(heavy[u]) dfs2(heavy[u], hd);
    for(int v:g[u]) if(v!=par[u] && v!=heavy[u]) dfs2(v, v);
    ed[u]=timer_;
}
 
struct BLK 
{
    int N,B,NB;
    vll val, tag;
    vector<unordered_map<ll,int>> freq;
    inline int bid(int i) const { return (i-1)/B; }
    inline int bl(int b) const { return b*B+1; }
    inline int br(int b) const { return min(N, (b+1)*B); }
    void init(int n, int B_=512)
    {
        N=n; B=max(256,B_); NB=(N+B-1)/B;
        val.assign(N+1,0); tag.assign(NB,0);
        freq.assign(NB, {});
    }
    void build(const vll &base)
    {
        ff(i,1,N) val[i]=base[i];
        ff(b,0,NB-1)
        {
            freq[b].clear();
            ff(i,bl(b),br(b)) ++freq[b][val[i]];
        }
    }
    void range_add(int l, int r, ll x)
    {
        if(l>r) return;
        int blid=bid(l), brid=bid(r);
        if(blid==brid)
        {
            auto &F=freq[blid];
            ff(i,l,r)
            {
                ll oldv=val[i];
                auto it=F.find(oldv);
                if(it!=F.end()){ if(--(it->se)==0) F.erase(it); }
                val[i]=oldv+x;
                ++F[val[i]];
            }
            return;
        }
        {
            auto &F=freq[blid];
            ff(i,l,br(blid))
            {
                ll oldv=val[i];
                auto it=F.find(oldv);
                if(it!=F.end()){ if(--(it->se)==0) F.erase(it); }
                val[i]=oldv+x;
                ++F[val[i]];
            }
        }
        ff(b,blid+1,brid-1) tag[b]+=x;
        {
            auto &F=freq[brid];
            ff(i,bl(brid),r)
            {
                ll oldv=val[i];
                auto it=F.find(oldv);
                if(it!=F.end()){ if(--(it->se)==0) F.erase(it); }
                val[i]=oldv+x;
                ++F[val[i]];
            }
        }
    }
    ll range_cnt(int l, int r) const
    {
        if(l>r) return 0;
        ll ans=0;
        int blid=bid(l), brid=bid(r);
        if(blid==brid)
        {
            ll tg=tag[blid];
            ff(i,l,r)
            {
                ll realv=val[i]+tg;
                if(spes.find(realv)!=spes.end()) ++ans;
            }
            return ans;
        }
        {
            ll tg=tag[blid];
            ff(i,l,br(blid)){
                ll realv=val[i]+tg;
                if(spes.find(realv)!=spes.end()) ++ans;
            }
        }
        ff(b,blid+1,brid-1)
        {
            ll tg=tag[b];
            const auto &F=freq[b];
            for(const auto &kv:F)
            {
                ll realv=kv.fi+tg;
                if(spes.find(realv)!=spes.end()) ans+=kv.se;
            }
        }
        {
            ll tg=tag[brid];
            ff(i,bl(brid),r)
            {
                ll realv=val[i]+tg;
                if(spes.find(realv)!=spes.end()) ++ans;
            }
        }
        return ans;
    }
} T;
 
inline void upd_path(int u, int v, ll x)
{
    while(head[u]!=head[v]){
        if(h[head[u]]<h[head[v]]) swap(u,v);
        T.range_add(st[head[u]], st[u], x);
        u=par[head[u]];
    }
    if(h[u]>h[v]) swap(u,v);
    T.range_add(st[u], st[v], x);
}
 
inline ll get_path(int u, int v)
{
    ll ans=0;
    while(head[u]!=head[v])
    {
        if(h[head[u]]<h[head[v]]) swap(u,v);
        ans+=T.range_cnt(st[head[u]], st[u]);
        u=par[head[u]];
    }
    if(h[u]>h[v]) swap(u,v);
    ans+=T.range_cnt(st[u], st[v]);
    return ans;
}
 
inline ll get_sub(int u)
{
    return T.range_cnt(st[u], ed[u]);
}
 
signed main(){
    rf();
    cin>>n>>q;
    ff(i,1,n) cin>>a[i];
    ff(i,1,n-1)
    {
        int u,v; cin>>u>>v;
        g[u].pb(v); g[v].pb(u);
    }
    dfs1(1,0); dfs2(1,1);
    vll base(timer_+1,0);
    ff(i,1,n) base[st[i]]=a[i];
    gen(0);
    sort(all(spev)); spev.erase(unique(all(spev)), spev.end());
    spes.reserve(spev.size()*2+7);
    for(ll v:spev) spes.insert(v);
    T.init(timer_,512);
    T.build(base);
    while(q--)
    {
        int op; cin>>op;
        if(op==1)
        {
            int u,v; ll x; cin>>u>>v>>x;
            upd_path(u,v,x);
        }
        else if(op==2)
        {
            int u,v; cin>>u>>v;
            cout<<get_path(u,v)<<nl;
        }
        else
        {
            int u; cin>>u;
            cout<<get_sub(u)<<nl;
        }
    }
    re;
}
 
				Ly8jcHJhZ21hIEdDQyBvcHRpbWl6ZSgiT2Zhc3QsdW5yb2xsLWxvb3BzIikKLy8jcHJhZ21hIEdDQyB0YXJnZXQoImF2eDIsdHVuZT1uYXRpdmUiKQojaW5jbHVkZSA8Yml0cy9zdGRjKysuaD4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCiNkZWZpbmUgZmlsZSAiZmFrZXJudW0iCiNkZWZpbmUgZmYoaSwgYSwgYikgZm9yKGF1dG8gaT0oYSk7IGk8PShiKTsgKytpKQojZGVmaW5lIGZmcihpLCBiLCBhKSBmb3IoYXV0byBpPShiKTsgaT49KGEpOyAtLWkpCiNkZWZpbmUgbmwgIlxuIgojZGVmaW5lIHNzICIgIgojZGVmaW5lIHBiIGVtcGxhY2VfYmFjawojZGVmaW5lIGZpIGZpcnN0CiNkZWZpbmUgc2Ugc2Vjb25kCiNkZWZpbmUgc3oocykgKGludClzLnNpemUoKQojZGVmaW5lIGFsbChzKSAocykuYmVnaW4oKSwgKHMpLmVuZCgpCiNkZWZpbmUgbXMoYSx4KSBtZW1zZXQoYSwgeCwgc2l6ZW9mIChhKSkKI2RlZmluZSBjbiBjb250aW51ZQojZGVmaW5lIHJlIGV4aXQoMCkKCnR5cGVkZWYgbG9uZyBsb25nIGxsOwp0eXBlZGVmIGxvbmcgZG91YmxlIGxkOwp0eXBlZGVmIHZlY3RvcjxpbnQ+IHZpOwp0eXBlZGVmIHZlY3RvcjxsbD4gdmxsOwp0eXBlZGVmIHBhaXI8aW50LCBpbnQ+IHBpaTsKdHlwZWRlZiBwYWlyPGxsLCBsbD4gcGxsOwp0eXBlZGVmIHZlY3RvcjxwaWk+IHZwaWk7CnR5cGVkZWYgdmVjdG9yPHBsbD4gdnBsbDsKCmNvbnN0IGludCBtb2Q9MWU5Kzc7CmNvbnN0IGludCBtYXhuPTFlNSsxNTsKY29uc3QgbGwgaW5mPTRlMTg7CgptdDE5OTM3XzY0IHJuZyhjaHJvbm86OnN0ZWFkeV9jbG9jazo6bm93KCkudGltZV9zaW5jZV9lcG9jaCgpLmNvdW50KCkpOwpsbCByYW4obGwgbCwgbGwgcikKewogICAgcmV0dXJuIHVuaWZvcm1faW50X2Rpc3RyaWJ1dGlvbjxsbD4gKGwsIHIpKHJuZyk7Cn0KCmlubGluZSB2b2lkIHJmKCl7CiAgICBpb3NfYmFzZTo6c3luY193aXRoX3N0ZGlvKGZhbHNlKTsKICAgIGNpbi50aWUobnVsbHB0cik7IGNvdXQudGllKG51bGxwdHIpOwogICAgaWYoZm9wZW4oZmlsZSIuaW5wIiwiciIpKXsKICAgICAgICBmcmVvcGVuKGZpbGUiLmlucCIsInIiLHN0ZGluKTsgZnJlb3BlbihmaWxlIi5vdXQiLCJ3IixzdGRvdXQpOwogICAgfQp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPiBpbmxpbmUgdm9pZCBhZGQoVCAmeCwgY29uc3QgVCAmeSkKewogICAgeCs9eTsKICAgIGlmKHg+PW1vZCkgeC09bW9kOwogICAgaWYoeDwwKSB4Kz1tb2Q7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQ+IGlubGluZSBib29sIG1heGkoVCAmYSwgVCBiKQp7CiAgICBpZihhPj1iKSByZXR1cm4gMDsKICAgIGE9YjsgcmV0dXJuIDE7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQ+IGlubGluZSBib29sIG1pbmkoVCAmYSwgVCBiKQp7CiAgICBpZihhPD1iKSByZXR1cm4gMDsKICAgIGE9YjsgcmV0dXJuIDE7Cn0KCmludCBuLHE7CmxsIGFbbWF4bl07CnZpIGdbbWF4bl07CmludCBwYXJbbWF4bl0sIGhbbWF4bl0sIGhlYXZ5W21heG5dLCBoZWFkW21heG5dLCBzdFttYXhuXSwgZWRbbWF4bl0sIHNpelttYXhuXSwgdGltZXJfPTA7Cgp2bGwgc3BldjsKdW5vcmRlcmVkX3NldDxsbD4gc3BlczsKCmlubGluZSBzdHJpbmcgdG9kZWNzdHIobGwgeCkKewogICAgaWYoeD09MCkgcmV0dXJuICIwIjsKICAgIHN0cmluZyBzOyB3aGlsZSh4KXsgcys9Y2hhcignMCcrKHglMTApKTsgeC89MTA7IH0gcmV2ZXJzZShhbGwocykpOyByZXR1cm4gczsKfQoKaW5saW5lIGxsIHBhbHN1Yihjb25zdCBzdHJpbmcgJnMpCnsKICAgIGludCBtPXN6KHMpOwogICAgbGwgYW5zPTA7CiAgICBmZihjLDAsbS0xKXsKICAgICAgICBpbnQgbD1jLCByPWM7CiAgICAgICAgd2hpbGUobD49MCAmJiByPG0gJiYgc1tsXT09c1tyXSl7ICsrYW5zOyAtLWw7ICsrcjsgfQogICAgfQogICAgZmYoYywwLG0tMil7CiAgICAgICAgaW50IGw9Yywgcj1jKzE7CiAgICAgICAgd2hpbGUobD49MCAmJiByPG0gJiYgc1tsXT09c1tyXSl7ICsrYW5zOyAtLWw7ICsrcjsgfQogICAgfQogICAgcmV0dXJuIGFuczsKfQoKaW5saW5lIGJvb2wgdmFsaWQobGwgeCkKewogICAgaWYoeDw9MCkgcmV0dXJuIDA7CiAgICBzdHJpbmcgcz10b2RlY3N0cih4KTsKICAgIGludCBjMz0wLGM2PTA7CiAgICBmb3IoY2hhciBjOnMpCiAgICB7CiAgICAgICAgaWYoYz09JzMnKSArK2MzOwogICAgICAgIGVsc2UgaWYoYz09JzYnKSArK2M2OwogICAgICAgIGVsc2UgcmV0dXJuIDA7CiAgICB9CiAgICBpZihjMyE9YzYpIHJldHVybiAwOwogICAgbGwgbWF1PTFMTCpzeihzKSooc3oocykrMSkvMjsKICAgIGxsIHR1PXBhbHN1YihzKTsKICAgIHJldHVybiB0dSoyPm1hdTsKfQoKdm9pZCBnZW4obGwgeCkKewogICAgaWYoeD4xZTE2KSByZXR1cm47CiAgICBpZih4IT0wICYmIHZhbGlkKHgpKSBzcGV2LnBiKHgpOwogICAgaWYoeD09MCl7IGdlbigzKTsgZ2VuKDYpOyB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgaWYoeDw9MWUxNSl7IGdlbih4KjEwKzMpOyBnZW4oeCoxMCs2KTsgfQogICAgfQp9CgppbnQgZGZzMShpbnQgdSwgaW50IHApCnsKICAgIHBhclt1XT1wOyBzaXpbdV09MTsgaW50IG14PTA7IGhlYXZ5W3VdPTA7CiAgICBmb3IoaW50IHY6Z1t1XSkgaWYodiE9cCkKICAgIHsKICAgICAgICBoW3ZdPWhbdV0rMTsKICAgICAgICBpbnQgcz1kZnMxKHYsdSk7CiAgICAgICAgc2l6W3VdKz1zOwogICAgICAgIGlmKHM+bXgpeyBteD1zOyBoZWF2eVt1XT12OyB9CiAgICB9CiAgICByZXR1cm4gc2l6W3VdOwp9CnZvaWQgZGZzMihpbnQgdSwgaW50IGhkKQp7CiAgICBoZWFkW3VdPWhkOyBzdFt1XT0rK3RpbWVyXzsKICAgIGlmKGhlYXZ5W3VdKSBkZnMyKGhlYXZ5W3VdLCBoZCk7CiAgICBmb3IoaW50IHY6Z1t1XSkgaWYodiE9cGFyW3VdICYmIHYhPWhlYXZ5W3VdKSBkZnMyKHYsIHYpOwogICAgZWRbdV09dGltZXJfOwp9CgpzdHJ1Y3QgQkxLIAp7CiAgICBpbnQgTixCLE5COwogICAgdmxsIHZhbCwgdGFnOwogICAgdmVjdG9yPHVub3JkZXJlZF9tYXA8bGwsaW50Pj4gZnJlcTsKICAgIGlubGluZSBpbnQgYmlkKGludCBpKSBjb25zdCB7IHJldHVybiAoaS0xKS9COyB9CiAgICBpbmxpbmUgaW50IGJsKGludCBiKSBjb25zdCB7IHJldHVybiBiKkIrMTsgfQogICAgaW5saW5lIGludCBicihpbnQgYikgY29uc3QgeyByZXR1cm4gbWluKE4sIChiKzEpKkIpOyB9CiAgICB2b2lkIGluaXQoaW50IG4sIGludCBCXz01MTIpCiAgICB7CiAgICAgICAgTj1uOyBCPW1heCgyNTYsQl8pOyBOQj0oTitCLTEpL0I7CiAgICAgICAgdmFsLmFzc2lnbihOKzEsMCk7IHRhZy5hc3NpZ24oTkIsMCk7CiAgICAgICAgZnJlcS5hc3NpZ24oTkIsIHt9KTsKICAgIH0KICAgIHZvaWQgYnVpbGQoY29uc3QgdmxsICZiYXNlKQogICAgewogICAgICAgIGZmKGksMSxOKSB2YWxbaV09YmFzZVtpXTsKICAgICAgICBmZihiLDAsTkItMSkKICAgICAgICB7CiAgICAgICAgICAgIGZyZXFbYl0uY2xlYXIoKTsKICAgICAgICAgICAgZmYoaSxibChiKSxicihiKSkgKytmcmVxW2JdW3ZhbFtpXV07CiAgICAgICAgfQogICAgfQogICAgdm9pZCByYW5nZV9hZGQoaW50IGwsIGludCByLCBsbCB4KQogICAgewogICAgICAgIGlmKGw+cikgcmV0dXJuOwogICAgICAgIGludCBibGlkPWJpZChsKSwgYnJpZD1iaWQocik7CiAgICAgICAgaWYoYmxpZD09YnJpZCkKICAgICAgICB7CiAgICAgICAgICAgIGF1dG8gJkY9ZnJlcVtibGlkXTsKICAgICAgICAgICAgZmYoaSxsLHIpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGxsIG9sZHY9dmFsW2ldOwogICAgICAgICAgICAgICAgYXV0byBpdD1GLmZpbmQob2xkdik7CiAgICAgICAgICAgICAgICBpZihpdCE9Ri5lbmQoKSl7IGlmKC0tKGl0LT5zZSk9PTApIEYuZXJhc2UoaXQpOyB9CiAgICAgICAgICAgICAgICB2YWxbaV09b2xkdit4OwogICAgICAgICAgICAgICAgKytGW3ZhbFtpXV07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICB7CiAgICAgICAgICAgIGF1dG8gJkY9ZnJlcVtibGlkXTsKICAgICAgICAgICAgZmYoaSxsLGJyKGJsaWQpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBsbCBvbGR2PXZhbFtpXTsKICAgICAgICAgICAgICAgIGF1dG8gaXQ9Ri5maW5kKG9sZHYpOwogICAgICAgICAgICAgICAgaWYoaXQhPUYuZW5kKCkpeyBpZigtLShpdC0+c2UpPT0wKSBGLmVyYXNlKGl0KTsgfQogICAgICAgICAgICAgICAgdmFsW2ldPW9sZHYreDsKICAgICAgICAgICAgICAgICsrRlt2YWxbaV1dOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGZmKGIsYmxpZCsxLGJyaWQtMSkgdGFnW2JdKz14OwogICAgICAgIHsKICAgICAgICAgICAgYXV0byAmRj1mcmVxW2JyaWRdOwogICAgICAgICAgICBmZihpLGJsKGJyaWQpLHIpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGxsIG9sZHY9dmFsW2ldOwogICAgICAgICAgICAgICAgYXV0byBpdD1GLmZpbmQob2xkdik7CiAgICAgICAgICAgICAgICBpZihpdCE9Ri5lbmQoKSl7IGlmKC0tKGl0LT5zZSk9PTApIEYuZXJhc2UoaXQpOyB9CiAgICAgICAgICAgICAgICB2YWxbaV09b2xkdit4OwogICAgICAgICAgICAgICAgKytGW3ZhbFtpXV07CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAgICBsbCByYW5nZV9jbnQoaW50IGwsIGludCByKSBjb25zdAogICAgewogICAgICAgIGlmKGw+cikgcmV0dXJuIDA7CiAgICAgICAgbGwgYW5zPTA7CiAgICAgICAgaW50IGJsaWQ9YmlkKGwpLCBicmlkPWJpZChyKTsKICAgICAgICBpZihibGlkPT1icmlkKQogICAgICAgIHsKICAgICAgICAgICAgbGwgdGc9dGFnW2JsaWRdOwogICAgICAgICAgICBmZihpLGwscikKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgbGwgcmVhbHY9dmFsW2ldK3RnOwogICAgICAgICAgICAgICAgaWYoc3Blcy5maW5kKHJlYWx2KSE9c3Blcy5lbmQoKSkgKythbnM7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIGFuczsKICAgICAgICB9CiAgICAgICAgewogICAgICAgICAgICBsbCB0Zz10YWdbYmxpZF07CiAgICAgICAgICAgIGZmKGksbCxicihibGlkKSl7CiAgICAgICAgICAgICAgICBsbCByZWFsdj12YWxbaV0rdGc7CiAgICAgICAgICAgICAgICBpZihzcGVzLmZpbmQocmVhbHYpIT1zcGVzLmVuZCgpKSArK2FuczsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBmZihiLGJsaWQrMSxicmlkLTEpCiAgICAgICAgewogICAgICAgICAgICBsbCB0Zz10YWdbYl07CiAgICAgICAgICAgIGNvbnN0IGF1dG8gJkY9ZnJlcVtiXTsKICAgICAgICAgICAgZm9yKGNvbnN0IGF1dG8gJmt2OkYpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGxsIHJlYWx2PWt2LmZpK3RnOwogICAgICAgICAgICAgICAgaWYoc3Blcy5maW5kKHJlYWx2KSE9c3Blcy5lbmQoKSkgYW5zKz1rdi5zZTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB7CiAgICAgICAgICAgIGxsIHRnPXRhZ1ticmlkXTsKICAgICAgICAgICAgZmYoaSxibChicmlkKSxyKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBsbCByZWFsdj12YWxbaV0rdGc7CiAgICAgICAgICAgICAgICBpZihzcGVzLmZpbmQocmVhbHYpIT1zcGVzLmVuZCgpKSArK2FuczsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gYW5zOwogICAgfQp9IFQ7CgppbmxpbmUgdm9pZCB1cGRfcGF0aChpbnQgdSwgaW50IHYsIGxsIHgpCnsKICAgIHdoaWxlKGhlYWRbdV0hPWhlYWRbdl0pewogICAgICAgIGlmKGhbaGVhZFt1XV08aFtoZWFkW3ZdXSkgc3dhcCh1LHYpOwogICAgICAgIFQucmFuZ2VfYWRkKHN0W2hlYWRbdV1dLCBzdFt1XSwgeCk7CiAgICAgICAgdT1wYXJbaGVhZFt1XV07CiAgICB9CiAgICBpZihoW3VdPmhbdl0pIHN3YXAodSx2KTsKICAgIFQucmFuZ2VfYWRkKHN0W3VdLCBzdFt2XSwgeCk7Cn0KCmlubGluZSBsbCBnZXRfcGF0aChpbnQgdSwgaW50IHYpCnsKICAgIGxsIGFucz0wOwogICAgd2hpbGUoaGVhZFt1XSE9aGVhZFt2XSkKICAgIHsKICAgICAgICBpZihoW2hlYWRbdV1dPGhbaGVhZFt2XV0pIHN3YXAodSx2KTsKICAgICAgICBhbnMrPVQucmFuZ2VfY250KHN0W2hlYWRbdV1dLCBzdFt1XSk7CiAgICAgICAgdT1wYXJbaGVhZFt1XV07CiAgICB9CiAgICBpZihoW3VdPmhbdl0pIHN3YXAodSx2KTsKICAgIGFucys9VC5yYW5nZV9jbnQoc3RbdV0sIHN0W3ZdKTsKICAgIHJldHVybiBhbnM7Cn0KCmlubGluZSBsbCBnZXRfc3ViKGludCB1KQp7CiAgICByZXR1cm4gVC5yYW5nZV9jbnQoc3RbdV0sIGVkW3VdKTsKfQoKc2lnbmVkIG1haW4oKXsKICAgIHJmKCk7CiAgICBjaW4+Pm4+PnE7CiAgICBmZihpLDEsbikgY2luPj5hW2ldOwogICAgZmYoaSwxLG4tMSkKICAgIHsKICAgICAgICBpbnQgdSx2OyBjaW4+PnU+PnY7CiAgICAgICAgZ1t1XS5wYih2KTsgZ1t2XS5wYih1KTsKICAgIH0KICAgIGRmczEoMSwwKTsgZGZzMigxLDEpOwogICAgdmxsIGJhc2UodGltZXJfKzEsMCk7CiAgICBmZihpLDEsbikgYmFzZVtzdFtpXV09YVtpXTsKICAgIGdlbigwKTsKICAgIHNvcnQoYWxsKHNwZXYpKTsgc3Bldi5lcmFzZSh1bmlxdWUoYWxsKHNwZXYpKSwgc3Bldi5lbmQoKSk7CiAgICBzcGVzLnJlc2VydmUoc3Bldi5zaXplKCkqMis3KTsKICAgIGZvcihsbCB2OnNwZXYpIHNwZXMuaW5zZXJ0KHYpOwogICAgVC5pbml0KHRpbWVyXyw1MTIpOwogICAgVC5idWlsZChiYXNlKTsKICAgIHdoaWxlKHEtLSkKICAgIHsKICAgICAgICBpbnQgb3A7IGNpbj4+b3A7CiAgICAgICAgaWYob3A9PTEpCiAgICAgICAgewogICAgICAgICAgICBpbnQgdSx2OyBsbCB4OyBjaW4+PnU+PnY+Png7CiAgICAgICAgICAgIHVwZF9wYXRoKHUsdix4KTsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZihvcD09MikKICAgICAgICB7CiAgICAgICAgICAgIGludCB1LHY7IGNpbj4+dT4+djsKICAgICAgICAgICAgY291dDw8Z2V0X3BhdGgodSx2KTw8bmw7CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICAgIGludCB1OyBjaW4+PnU7CiAgICAgICAgICAgIGNvdXQ8PGdldF9zdWIodSk8PG5sOwogICAgICAgIH0KICAgIH0KICAgIHJlOwp9Cg==