#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define REP(i,b) FOR(i,0,b)
#define PB push_back
#define MP make_pair
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
int read(){
int i;
scanf("%d",&i);
return i;
}
const int maxN=100000;
const int maxQ=100000;
const int B=400;
pii vv[maxN];
vector<int> orgT[maxN];
struct Event{
int t,a,b,c;
} evs[maxQ];
struct Edge{
int to,dist;
};
struct Query{
int i,a,b;
};
int ans[maxQ];
struct Range{
int l,r,v;
};
struct MyDeque{
Range buf[B*4+1];
int mx[B*4+1];
int b,m,e;
void Init(){
b=B*2;
m=B*2;
e=B*2;
}
void Reset(){
m=(b+e)/2;
mx[m-1]=buf[m-1].v;
for(int i=m-2;i>=b;i--)
mx[i]=max(mx[i+1],buf[i].v);
mx[m]=buf[m].v;
FOR(i,m+1,e)
mx[i]=max(mx[i-1],buf[i].v);
}
int FrontMax(){
return b<m?mx[b]:INT_MIN;
}
void PushFront(Range x){
buf[b-1]=x;
mx[b-1]=max(x.v,FrontMax());
b--;
}
Range PopFront(){
if(b==m){
if(e==b+1)
return buf[--e];
else
Reset();
}
return buf[b++];
}
int BackMax(){
return m<e?mx[e-1]:INT_MIN;
}
void PushBack(Range x){
buf[e]=x;
mx[e]=max(x.v,BackMax());
e++;
}
Range PopBack(){
if(m==e){
if(e==b+1)
return buf[b++];
else
Reset();
}
return buf[--e];
}
bool Empty(){
return b==e;
}
int GetMax(){
return max(FrontMax(),BackMax());
}
} mdq;
int na[B*2],ansRange[B*2][2];
void Sub(const vector<Query>& lq,const vector<Query>& rq,const vector<int>& arr){
const int len=arr.size(),qc=lq.size()+rq.size();
int li=0,ri=0,al=0,ar=len-1;
mdq.Init();
mdq.PushBack(Range{0,len-1,INT_MIN});
REP(i,qc){
Query cur;
bool leftQ;
if(li==(int)lq.size()){
cur=rq[ri++];
leftQ=false;
}else if(ri==(int)rq.size()){
cur=lq[li++];
leftQ=true;
}else if(lq[li].i<rq[ri].i){
cur=lq[li++];
leftQ=true;
}else{
cur=rq[ri++];
leftQ=false;
}
na[i]=-1;
if(cur.a!=-1){
cur.b=min(cur.b,len-1);
if(leftQ){
Range w=Range{0,cur.b,cur.a};
while(!mdq.Empty()){
Range x=mdq.PopFront();
if(w.r<x.r){
x.l=w.r+1;
mdq.PushFront(x);
break;
}
}
mdq.PushFront(w);
al=max(al,cur.b+1);
}else{
Range w=Range{len-1-cur.b,len-1,cur.a};
while(!mdq.Empty()){
Range x=mdq.PopBack();
if(x.l<w.l){
x.r=w.l-1;
mdq.PushBack(x);
break;
}
}
mdq.PushBack(w);
ar=min(ar,len-1-cur.b-1);
}
}else if(leftQ){
ans[cur.i]=max(ans[cur.i],mdq.GetMax());
na[i]=cur.i;
}
ansRange[i][0]=al;
ansRange[i][1]=ar;
}
int lastL=-1,lastR=-1,mx=INT_MIN;
for(int i=qc-1;i>=0;i--)
if(na[i]!=-1)
if(ansRange[i][0]<=ansRange[i][1]){
if(lastL==-1&&lastR==-1){
FOR(j,ansRange[i][0],ansRange[i][1]+1)
mx=max(mx,arr[j]);
}else{
FOR(j,ansRange[i][0],lastL)
mx=max(mx,arr[j]);
FOR(j,lastR+1,ansRange[i][1]+1)
mx=max(mx,arr[j]);
}
lastL=ansRange[i][0];
lastR=ansRange[i][1];
ans[na[i]]=max(ans[na[i]],mx);
}
}
bool nowUse[maxN];
vector<int> orgArr[B*4];
vector<Edge> cmpT[B*4];
vector<Query> cmpQ[B*4];
int cmpIdx[maxN],idxInv[B*4],cmpPar[B*4],orgPar[maxN],cmpDep[B*4],raw[B*4];
int MarkDfs(int v,int p,int& idx){
orgPar[v]=p;
int k=0,ret=0;
for(auto&& i:orgT[v])
if(i!=p)
k+=MarkDfs(i,v,idx);
if(k)ret=1;
if(k>=2)
nowUse[v]=true;
if(nowUse[v]){
cmpIdx[v]=idx;
raw[idx]=vv[v].second;
idxInv[idx++]=v;
ret=1;
}
return ret;
}
void SetDepth(int v,int p,int d){
cmpDep[v]=d;
for(auto&& e:cmpT[v])
if(e.to!=p)
SetDepth(e.to,v,d+1);
}
void UpdateDfs(int v,int p,int i,int val,int d){
if(d<0)
return;
raw[v]=val;
cmpQ[v].PB(Query{i,val,d});
for(auto&& e:cmpT[v])
if(e.to!=p)
UpdateDfs(e.to,v,i,val,d-e.dist);
}
struct DistVal{
int d;
pii v;
} dvBuf[B];
void ReplaceDfs(int v,int p,int idx,int d){
if(nowUse[v]&&p!=-1)
return;
if(idx>=0&&dvBuf[idx].d<d)
idx--;
if(idx==-1)
return;
vv[v]=max(vv[v],dvBuf[idx].v);
for(auto&& i:orgT[v])
if(i!=p)
ReplaceDfs(i,v,idx,d+1);
}
void Solve(int evb,int eve){
memset(nowUse,false,sizeof(nowUse));
FOR(i,evb,eve)
if(evs[i].t==1){
nowUse[evs[i].a]=true;
}else{
nowUse[evs[i].a]=true;
nowUse[evs[i].b]=true;
}
int root=evs[evb].a;
int cmpSize=0;
MarkDfs(root,-1,cmpSize);
root=cmpIdx[root];
REP(i,cmpSize){
cmpT[i].clear();
cmpQ[i].clear();
}
REP(i,cmpSize)if(i!=root){
int v=idxInv[i],x=orgPar[v],d=1;
orgArr[i].clear();
orgArr[i].PB(vv[v].second);
while(!nowUse[x]){
orgArr[i].PB(vv[x].second);
x=orgPar[x];
d++;
}
orgArr[i].PB(vv[x].second);
cmpPar[i]=cmpIdx[x];
cmpT[i].PB(Edge{cmpPar[i],d});
cmpT[cmpPar[i]].PB(Edge{i,d});
}
SetDepth(root,-1,0);
FOR(i,evb,eve)
if(evs[i].t==1)
UpdateDfs(cmpIdx[evs[i].a],-1,i,evs[i].c,evs[i].b);
else{
int x=cmpIdx[evs[i].a],y=cmpIdx[evs[i].b];
if(x==y){
ans[i]=raw[x];
}else{
if(cmpDep[x]>cmpDep[y])
swap(x,y);
while(cmpDep[x]<cmpDep[y]){
cmpQ[y].PB(Query{i,-1,evs[i].c});
y=cmpPar[y];
}
while(x!=y){
cmpQ[x].PB(Query{i,-1,evs[i].c});
x=cmpPar[x];
cmpQ[y].PB(Query{i,-1,evs[i].c});
y=cmpPar[y];
}
}
}
REP(i,cmpSize)if(i!=root)
Sub(cmpQ[i],cmpQ[cmpPar[i]],orgArr[i]);
REP(i,cmpSize){
int k=0;
for(auto q:cmpQ[i])
if(q.a!=-1){
while(k){
DistVal dv=dvBuf[k-1];
if(dv.d>q.b)
break;
k--;
}
dvBuf[k++]=DistVal{q.b,MP(q.i,q.a)};
}
ReplaceDfs(idxInv[i],-1,k-1,0);
}
}
int main(){
int n=read(),q=read();
REP(i,n)
vv[i]=MP(-1,read());
REP(i,n-1){
int a=read()-1,b=read()-1;
orgT[a].PB(b);
orgT[b].PB(a);
}
REP(i,q){
int t=read(),a=read(),b=read(),c=read();
if(t==1)a--;
if(t==2)a--,b--,c=i;
evs[i]=Event{t,a,b,c};
if(i%B==B-1)
Solve(i+1-B,i+1);
}
if(q%B)
Solve(q/B*B,q);
REP(i,q)
if(evs[i].t==2)
printf("%d\n",ans[i]);
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CiAKI2RlZmluZSBGT1IoaSxhLGIpIGZvcihpbnQgaT1hO2k8YjtpKyspCiNkZWZpbmUgUkVQKGksYikgRk9SKGksMCxiKQojZGVmaW5lIFBCIHB1c2hfYmFjawojZGVmaW5lIE1QIG1ha2VfcGFpcgogCnVzaW5nIG5hbWVzcGFjZSBzdGQ7CiAKdHlwZWRlZiBsb25nIGxvbmcgbGw7CnR5cGVkZWYgcGFpcjxpbnQsaW50PiBwaWk7CiAKaW50IHJlYWQoKXsKCWludCBpOwoJc2NhbmYoIiVkIiwmaSk7CglyZXR1cm4gaTsKfQogCmNvbnN0IGludCBtYXhOPTEwMDAwMDsKY29uc3QgaW50IG1heFE9MTAwMDAwOwpjb25zdCBpbnQgQj00MDA7CnBpaSB2dlttYXhOXTsKdmVjdG9yPGludD4gb3JnVFttYXhOXTsKIApzdHJ1Y3QgRXZlbnR7CglpbnQgdCxhLGIsYzsKfSBldnNbbWF4UV07CnN0cnVjdCBFZGdlewoJaW50IHRvLGRpc3Q7Cn07CnN0cnVjdCBRdWVyeXsKCWludCBpLGEsYjsKfTsKaW50IGFuc1ttYXhRXTsKc3RydWN0IFJhbmdlewoJaW50IGwscix2Owp9OwpzdHJ1Y3QgTXlEZXF1ZXsKCVJhbmdlIGJ1ZltCKjQrMV07CglpbnQgbXhbQio0KzFdOwoJaW50IGIsbSxlOwoJdm9pZCBJbml0KCl7CgkJYj1CKjI7CgkJbT1CKjI7CgkJZT1CKjI7Cgl9Cgl2b2lkIFJlc2V0KCl7CgkJbT0oYitlKS8yOwoJCW14W20tMV09YnVmW20tMV0udjsKCQlmb3IoaW50IGk9bS0yO2k+PWI7aS0tKQoJCQlteFtpXT1tYXgobXhbaSsxXSxidWZbaV0udik7CgkJbXhbbV09YnVmW21dLnY7CgkJRk9SKGksbSsxLGUpCgkJCW14W2ldPW1heChteFtpLTFdLGJ1ZltpXS52KTsKCX0KCWludCBGcm9udE1heCgpewoJCXJldHVybiBiPG0/bXhbYl06SU5UX01JTjsKCX0KCXZvaWQgUHVzaEZyb250KFJhbmdlIHgpewoJCWJ1ZltiLTFdPXg7CgkJbXhbYi0xXT1tYXgoeC52LEZyb250TWF4KCkpOwoJCWItLTsKCX0KCVJhbmdlIFBvcEZyb250KCl7CgkJaWYoYj09bSl7CgkJCWlmKGU9PWIrMSkKCQkJCXJldHVybiBidWZbLS1lXTsKCQkJZWxzZQoJCQkJUmVzZXQoKTsKCQl9CgkJcmV0dXJuIGJ1ZltiKytdOwoJfQoJaW50IEJhY2tNYXgoKXsKCQlyZXR1cm4gbTxlP214W2UtMV06SU5UX01JTjsKCX0KCXZvaWQgUHVzaEJhY2soUmFuZ2UgeCl7CgkJYnVmW2VdPXg7CgkJbXhbZV09bWF4KHgudixCYWNrTWF4KCkpOwoJCWUrKzsKCX0KCVJhbmdlIFBvcEJhY2soKXsKCQlpZihtPT1lKXsKCQkJaWYoZT09YisxKQoJCQkJcmV0dXJuIGJ1ZltiKytdOwoJCQllbHNlCgkJCQlSZXNldCgpOwoJCX0KCQlyZXR1cm4gYnVmWy0tZV07Cgl9Cglib29sIEVtcHR5KCl7CgkJcmV0dXJuIGI9PWU7Cgl9CglpbnQgR2V0TWF4KCl7CgkJcmV0dXJuIG1heChGcm9udE1heCgpLEJhY2tNYXgoKSk7Cgl9Cn0gbWRxOwppbnQgbmFbQioyXSxhbnNSYW5nZVtCKjJdWzJdOwp2b2lkIFN1Yihjb25zdCB2ZWN0b3I8UXVlcnk+JiBscSxjb25zdCB2ZWN0b3I8UXVlcnk+JiBycSxjb25zdCB2ZWN0b3I8aW50PiYgYXJyKXsKCWNvbnN0IGludCBsZW49YXJyLnNpemUoKSxxYz1scS5zaXplKCkrcnEuc2l6ZSgpOwoJaW50IGxpPTAscmk9MCxhbD0wLGFyPWxlbi0xOwoJbWRxLkluaXQoKTsKCW1kcS5QdXNoQmFjayhSYW5nZXswLGxlbi0xLElOVF9NSU59KTsKCVJFUChpLHFjKXsKCQlRdWVyeSBjdXI7CgkJYm9vbCBsZWZ0UTsKCQlpZihsaT09KGludClscS5zaXplKCkpewoJCQljdXI9cnFbcmkrK107CgkJCWxlZnRRPWZhbHNlOwoJCX1lbHNlIGlmKHJpPT0oaW50KXJxLnNpemUoKSl7CgkJCWN1cj1scVtsaSsrXTsKCQkJbGVmdFE9dHJ1ZTsKCQl9ZWxzZSBpZihscVtsaV0uaTxycVtyaV0uaSl7CgkJCWN1cj1scVtsaSsrXTsKCQkJbGVmdFE9dHJ1ZTsKCQl9ZWxzZXsKCQkJY3VyPXJxW3JpKytdOwoJCQlsZWZ0UT1mYWxzZTsKCQl9CgkJbmFbaV09LTE7CgkJaWYoY3VyLmEhPS0xKXsKCQkJY3VyLmI9bWluKGN1ci5iLGxlbi0xKTsKCQkJaWYobGVmdFEpewoJCQkJUmFuZ2Ugdz1SYW5nZXswLGN1ci5iLGN1ci5hfTsKCQkJCXdoaWxlKCFtZHEuRW1wdHkoKSl7CgkJCQkJUmFuZ2UgeD1tZHEuUG9wRnJvbnQoKTsKCQkJCQlpZih3LnI8eC5yKXsKCQkJCQkJeC5sPXcucisxOwoJCQkJCQltZHEuUHVzaEZyb250KHgpOwoJCQkJCQlicmVhazsKCQkJCQl9CgkJCQl9CgkJCQltZHEuUHVzaEZyb250KHcpOwoJCQkJYWw9bWF4KGFsLGN1ci5iKzEpOwoJCQl9ZWxzZXsKCQkJCVJhbmdlIHc9UmFuZ2V7bGVuLTEtY3VyLmIsbGVuLTEsY3VyLmF9OwoJCQkJd2hpbGUoIW1kcS5FbXB0eSgpKXsKCQkJCQlSYW5nZSB4PW1kcS5Qb3BCYWNrKCk7CgkJCQkJaWYoeC5sPHcubCl7CgkJCQkJCXgucj13LmwtMTsKCQkJCQkJbWRxLlB1c2hCYWNrKHgpOwoJCQkJCQlicmVhazsKCQkJCQl9CgkJCQl9CgkJCQltZHEuUHVzaEJhY2sodyk7CgkJCQlhcj1taW4oYXIsbGVuLTEtY3VyLmItMSk7CgkJCX0KCQl9ZWxzZSBpZihsZWZ0USl7CgkJCWFuc1tjdXIuaV09bWF4KGFuc1tjdXIuaV0sbWRxLkdldE1heCgpKTsKCQkJbmFbaV09Y3VyLmk7CgkJfQoJCWFuc1JhbmdlW2ldWzBdPWFsOwoJCWFuc1JhbmdlW2ldWzFdPWFyOwoJfQoJaW50IGxhc3RMPS0xLGxhc3RSPS0xLG14PUlOVF9NSU47Cglmb3IoaW50IGk9cWMtMTtpPj0wO2ktLSkKCQlpZihuYVtpXSE9LTEpCgkJCWlmKGFuc1JhbmdlW2ldWzBdPD1hbnNSYW5nZVtpXVsxXSl7CgkJCQlpZihsYXN0TD09LTEmJmxhc3RSPT0tMSl7CgkJCQkJRk9SKGosYW5zUmFuZ2VbaV1bMF0sYW5zUmFuZ2VbaV1bMV0rMSkKCQkJCQkJbXg9bWF4KG14LGFycltqXSk7CgkJCQl9ZWxzZXsKCQkJCQlGT1IoaixhbnNSYW5nZVtpXVswXSxsYXN0TCkKCQkJCQkJbXg9bWF4KG14LGFycltqXSk7CgkJCQkJRk9SKGosbGFzdFIrMSxhbnNSYW5nZVtpXVsxXSsxKQoJCQkJCQlteD1tYXgobXgsYXJyW2pdKTsKCQkJCX0KCQkJCWxhc3RMPWFuc1JhbmdlW2ldWzBdOwoJCQkJbGFzdFI9YW5zUmFuZ2VbaV1bMV07CgkJCQlhbnNbbmFbaV1dPW1heChhbnNbbmFbaV1dLG14KTsKCQkJfQp9CiAKYm9vbCBub3dVc2VbbWF4Tl07CnZlY3RvcjxpbnQ+IG9yZ0FycltCKjRdOwp2ZWN0b3I8RWRnZT4gY21wVFtCKjRdOwp2ZWN0b3I8UXVlcnk+IGNtcFFbQio0XTsKaW50IGNtcElkeFttYXhOXSxpZHhJbnZbQio0XSxjbXBQYXJbQio0XSxvcmdQYXJbbWF4Tl0sY21wRGVwW0IqNF0scmF3W0IqNF07CmludCBNYXJrRGZzKGludCB2LGludCBwLGludCYgaWR4KXsKCW9yZ1Bhclt2XT1wOwoJaW50IGs9MCxyZXQ9MDsKCWZvcihhdXRvJiYgaTpvcmdUW3ZdKQoJCWlmKGkhPXApCgkJCWsrPU1hcmtEZnMoaSx2LGlkeCk7CglpZihrKXJldD0xOwoJaWYoaz49MikKCQlub3dVc2Vbdl09dHJ1ZTsKCWlmKG5vd1VzZVt2XSl7CgkJY21wSWR4W3ZdPWlkeDsKCQlyYXdbaWR4XT12dlt2XS5zZWNvbmQ7CgkJaWR4SW52W2lkeCsrXT12OwoJCXJldD0xOwoJfQoJcmV0dXJuIHJldDsKfQp2b2lkIFNldERlcHRoKGludCB2LGludCBwLGludCBkKXsKCWNtcERlcFt2XT1kOwoJZm9yKGF1dG8mJiBlOmNtcFRbdl0pCgkJaWYoZS50byE9cCkKCQkJU2V0RGVwdGgoZS50byx2LGQrMSk7Cn0Kdm9pZCBVcGRhdGVEZnMoaW50IHYsaW50IHAsaW50IGksaW50IHZhbCxpbnQgZCl7CglpZihkPDApCgkJcmV0dXJuOwoJcmF3W3ZdPXZhbDsKCWNtcFFbdl0uUEIoUXVlcnl7aSx2YWwsZH0pOwoJZm9yKGF1dG8mJiBlOmNtcFRbdl0pCgkJaWYoZS50byE9cCkKCQkJVXBkYXRlRGZzKGUudG8sdixpLHZhbCxkLWUuZGlzdCk7Cn0Kc3RydWN0IERpc3RWYWx7CglpbnQgZDsKCXBpaSB2Owp9IGR2QnVmW0JdOwp2b2lkIFJlcGxhY2VEZnMoaW50IHYsaW50IHAsaW50IGlkeCxpbnQgZCl7CglpZihub3dVc2Vbdl0mJnAhPS0xKQoJCXJldHVybjsKCWlmKGlkeD49MCYmZHZCdWZbaWR4XS5kPGQpCgkJCWlkeC0tOwoJaWYoaWR4PT0tMSkKCQlyZXR1cm47Cgl2dlt2XT1tYXgodnZbdl0sZHZCdWZbaWR4XS52KTsKCWZvcihhdXRvJiYgaTpvcmdUW3ZdKQoJCWlmKGkhPXApCgkJCVJlcGxhY2VEZnMoaSx2LGlkeCxkKzEpOwp9CnZvaWQgU29sdmUoaW50IGV2YixpbnQgZXZlKXsKCW1lbXNldChub3dVc2UsZmFsc2Usc2l6ZW9mKG5vd1VzZSkpOwoJRk9SKGksZXZiLGV2ZSkKCQlpZihldnNbaV0udD09MSl7CgkJCW5vd1VzZVtldnNbaV0uYV09dHJ1ZTsKCQl9ZWxzZXsKCQkJbm93VXNlW2V2c1tpXS5hXT10cnVlOwoJCQlub3dVc2VbZXZzW2ldLmJdPXRydWU7CgkJfQoJaW50IHJvb3Q9ZXZzW2V2Yl0uYTsKCWludCBjbXBTaXplPTA7CglNYXJrRGZzKHJvb3QsLTEsY21wU2l6ZSk7Cglyb290PWNtcElkeFtyb290XTsKCVJFUChpLGNtcFNpemUpewoJCWNtcFRbaV0uY2xlYXIoKTsKCQljbXBRW2ldLmNsZWFyKCk7Cgl9CglSRVAoaSxjbXBTaXplKWlmKGkhPXJvb3QpewoJCWludCB2PWlkeEludltpXSx4PW9yZ1Bhclt2XSxkPTE7CgkJb3JnQXJyW2ldLmNsZWFyKCk7CgkJb3JnQXJyW2ldLlBCKHZ2W3ZdLnNlY29uZCk7CgkJd2hpbGUoIW5vd1VzZVt4XSl7CgkJCW9yZ0FycltpXS5QQih2dlt4XS5zZWNvbmQpOwoJCQl4PW9yZ1Bhclt4XTsKCQkJZCsrOwoJCX0KCQlvcmdBcnJbaV0uUEIodnZbeF0uc2Vjb25kKTsKCQljbXBQYXJbaV09Y21wSWR4W3hdOwoJCWNtcFRbaV0uUEIoRWRnZXtjbXBQYXJbaV0sZH0pOwoJCWNtcFRbY21wUGFyW2ldXS5QQihFZGdle2ksZH0pOwoJfQoJU2V0RGVwdGgocm9vdCwtMSwwKTsKCUZPUihpLGV2YixldmUpCgkJaWYoZXZzW2ldLnQ9PTEpCgkJCVVwZGF0ZURmcyhjbXBJZHhbZXZzW2ldLmFdLC0xLGksZXZzW2ldLmMsZXZzW2ldLmIpOwoJCWVsc2V7CgkJCWludCB4PWNtcElkeFtldnNbaV0uYV0seT1jbXBJZHhbZXZzW2ldLmJdOwoJCQlpZih4PT15KXsKCQkJCWFuc1tpXT1yYXdbeF07CgkJCX1lbHNlewoJCQkJaWYoY21wRGVwW3hdPmNtcERlcFt5XSkKCQkJCQlzd2FwKHgseSk7CgkJCQl3aGlsZShjbXBEZXBbeF08Y21wRGVwW3ldKXsKCQkJCQljbXBRW3ldLlBCKFF1ZXJ5e2ksLTEsZXZzW2ldLmN9KTsKCQkJCQl5PWNtcFBhclt5XTsKCQkJCX0KCQkJCXdoaWxlKHghPXkpewoJCQkJCWNtcFFbeF0uUEIoUXVlcnl7aSwtMSxldnNbaV0uY30pOwoJCQkJCXg9Y21wUGFyW3hdOwoJCQkJCWNtcFFbeV0uUEIoUXVlcnl7aSwtMSxldnNbaV0uY30pOwoJCQkJCXk9Y21wUGFyW3ldOwoJCQkJfQoJCQl9CgkJfQoJUkVQKGksY21wU2l6ZSlpZihpIT1yb290KQoJCVN1YihjbXBRW2ldLGNtcFFbY21wUGFyW2ldXSxvcmdBcnJbaV0pOwoJUkVQKGksY21wU2l6ZSl7CgkJaW50IGs9MDsKCQlmb3IoYXV0byBxOmNtcFFbaV0pCgkJCWlmKHEuYSE9LTEpewoJCQkJd2hpbGUoayl7CgkJCQkJRGlzdFZhbCBkdj1kdkJ1ZltrLTFdOwoJCQkJCWlmKGR2LmQ+cS5iKQoJCQkJCQlicmVhazsKCQkJCQlrLS07CgkJCQl9CgkJCQlkdkJ1ZltrKytdPURpc3RWYWx7cS5iLE1QKHEuaSxxLmEpfTsKCQkJfQoJCVJlcGxhY2VEZnMoaWR4SW52W2ldLC0xLGstMSwwKTsKCX0KfQogCmludCBtYWluKCl7CglpbnQgbj1yZWFkKCkscT1yZWFkKCk7CglSRVAoaSxuKQoJCXZ2W2ldPU1QKC0xLHJlYWQoKSk7CglSRVAoaSxuLTEpewoJCWludCBhPXJlYWQoKS0xLGI9cmVhZCgpLTE7CgkJb3JnVFthXS5QQihiKTsKCQlvcmdUW2JdLlBCKGEpOwoJfQoJUkVQKGkscSl7CgkJaW50IHQ9cmVhZCgpLGE9cmVhZCgpLGI9cmVhZCgpLGM9cmVhZCgpOwoJCWlmKHQ9PTEpYS0tOwoJCWlmKHQ9PTIpYS0tLGItLSxjPWk7CgkJZXZzW2ldPUV2ZW50e3QsYSxiLGN9OwoJCWlmKGklQj09Qi0xKQoJCQlTb2x2ZShpKzEtQixpKzEpOwoJfQoJaWYocSVCKQoJCVNvbHZlKHEvQipCLHEpOwoJUkVQKGkscSkKCQlpZihldnNbaV0udD09MikKCQkJcHJpbnRmKCIlZFxuIixhbnNbaV0pOwp9Cg==