Cod sursa(job #723925)

Utilizator ionutz32Ilie Ionut ionutz32 Data 26 martie 2012 01:23:08
Problema Heavy Path Decomposition Scor 20
Compilator fpc Status done
Runda Arhiva educationala Marime 6.77 kb
type ref=^nod;
nod=record
    nr:longint;
    adr:ref;
    end;
var arb,lanturi:array[0..100005] of ref;
t:array[0..17,0..100005] of longint;
v,poz,path,tata,len,arbpoz,lev:array[0..100005] of longint;
arbint:array[0..400005] of longint;
n,m,i,x,y,nrl,j,max,max2,val,contor,t2,z,left:longint;
u:ref;
f,g:text;
procedure df(nod,nivel:longint;var rang:longint);
          var u:ref;
          max,temp:longint;
          begin
          lev[nod]:=nivel;
          u:=arb[nod];
          rang:=1;
          max:=0;
          while u<>nil do
                begin
                if u^.nr<>t[0,nod] then
                   begin
                   inc(rang);
                   t[0,u^.nr]:=nod;
                   df(u^.nr,nivel+1,temp);
                   if temp>max then
                      begin
                      max:=temp;
                      path[nod]:=path[u^.nr];
                      end;
                   tata[path[u^.nr]]:=nod;
                   end;
                u:=u^.adr;
                end;
          if rang=1 then
             begin
             inc(nrl);
             len[nrl]:=1;
             new(lanturi[nrl]);
             lanturi[nrl]^.nr:=nod;
             lanturi[nrl]^.adr:=nil;
             path[nod]:=nrl;
             end
          else
              begin
              new(u);
              u^.nr:=nod;
              u^.adr:=lanturi[path[nod]];
              lanturi[path[nod]]:=u;
              inc(len[path[nod]]);
              end;
          end;
procedure update(p,a,b,nod:longint);
          var mid:longint;
          begin
          if a=b then
             begin
             arbint[left+nod]:=val;
             if left+nod>max2 then
                max2:=left+nod;
             exit;
             end;
          mid:=a+(b-a) shr 1;
          if p<=mid then
             update(p,a,mid,nod shl 1)
          else
              update(p,mid+1,b,(nod shl 1)+1);
          if arbint[left+(nod shl 1)]>arbint[left+(nod shl 1)+1] then
             arbint[left+nod]:=arbint[left+(nod shl 1)]
          else
              arbint[left+nod]:=arbint[left+(nod shl 1)+1];
          end;
function minim(a,b:longint):longint;
         begin
         if a<b then
            minim:=a
         else
             minim:=b;
         end;
function maxim(a,b:longint):longint;
         begin
         if a>b then
            maxim:=a
         else
             maxim:=b;
         end;
function query_ai(q1,q2,a,b,nod:longint):longint;
         var mid,temp,temp2:longint;
         begin
         if (q1<=a) and (q2>=b) then
            query_ai:=arbint[left+nod]
         else
             begin
             mid:=a+(b-a) shr 1;
             if q1<=mid then
                temp:=query_ai(q1,minim(mid,q2),a,mid,nod shl 1)
             else
                 temp:=0;
             if q2>mid then
                temp2:=query_ai(maxim(mid+1,q1),q2,mid+1,b,(nod shl 1)+1)
             else
                 temp2:=0;
             if temp>temp2 then
                query_ai:=temp
             else
                 query_ai:=temp2;
             end;
         end;
function lca(nod1,nod2:longint):longint;
         var aux,pow,q:longint;
         begin
         if lev[nod1]>lev[nod2] then
            begin
            aux:=nod1;
            nod1:=nod2;
            nod2:=aux;
            end;
         if lev[nod1]<lev[nod2] then
            begin
            pow:=1;
            q:=0;
            while pow shl 1<=lev[nod2]-1 do
                  begin
                  pow:=pow shl 1;
                  inc(q);
                  end;
            while lev[nod1]<lev[nod2] do
                  begin
                  if lev[t[q,nod2]]>=lev[nod1] then
                     nod2:=t[q,nod2];
                  dec(q);
                  end;
            end;
         if nod1=nod2 then
            begin
            lca:=nod1;
            exit;
            end;
         if (nod1=1) or (nod2=1) then
            begin
            lca:=1;
            exit;
            end;
         if t[0,nod1]<>t[0,nod2] then
            begin
            pow:=1;
            q:=0;
            while pow shl 1<=lev[nod1]-2 do
                  begin
                  pow:=pow shl 1;
                  inc(q);
                  end;
            while t[0,nod1]<>t[0,nod2] do
                  begin
                  if t[q,nod1]<>t[q,nod2] then
                     begin
                     nod1:=t[q,nod1];
                     nod2:=t[q,nod2];
                     end;
                  dec(q);
                  end;
            end;
         lca:=t[0,nod1];
         end;
function query(stramos,nod:longint):longint;
         var ret,temp:longint;
         begin
         ret:=v[nod];
         while stramos<>nod do
               if path[stramos]=path[nod] then
                  begin
                  left:=arbpoz[path[nod]];
                  temp:=query_ai(poz[stramos],poz[nod],1,len[path[nod]],1);
                  if temp>ret then
                     query:=temp
                  else
                      query:=ret;
                  exit;
                  end
               else
                   begin
                   left:=arbpoz[path[nod]];
                   temp:=query_ai(1,poz[nod],1,len[path[nod]],1);
                   if temp>ret then
                      ret:=temp;
                   nod:=tata[path[nod]];
                   if v[nod]>ret then
                      ret:=v[nod];
                   end;
         query:=ret;
         end;
begin
assign(f,'heavypath.in');
assign(g,'heavypath.out');
reset(f);rewrite(g);
readln(f,n,m);
for i:=1 to n do
    read(f,v[i]);
for i:=1 to n-1 do
    begin
    readln(f,x,y);
    new(u);
    u^.nr:=y;
    u^.adr:=arb[x];
    arb[x]:=u;
    new(u);
    u^.nr:=x;
    u^.adr:=arb[y];
    arb[y]:=u;
    end;
df(1,1,x);
tata[path[1]]:=0;
for i:=1 to nrl do
    begin
    arbpoz[i]:=max;
    u:=lanturi[i];
    j:=0;
    while u<>nil do
          begin
          inc(j);
          poz[u^.nr]:=j;
          val:=v[u^.nr];
          left:=max;
          update(j,1,len[i],1);
          u:=u^.adr;
          end;
    max:=max2;
    end;
i:=1;
while 1 shl i<n do
      begin
      for j:=1 to n do
          t[i,j]:=t[i-1,t[i-1,j]];
      inc(i);
      end;
for contor:=1 to m do
    begin
    readln(f,t2,x,y);
    if t2=1 then
       begin
       z:=lca(x,y);
       max:=query(z,x);
       max2:=query(z,y);
       if max>max2 then
          writeln(g,max)
       else
           writeln(g,max2);
       end
    else
        begin
        v[x]:=y;
        val:=y;
        left:=arbpoz[path[x]];
        update(poz[x],1,len[path[x]],1);
        end;
    end;
close(f);close(g);
end.