Cod sursa(job #2765989)

Utilizator cadmium_Voicu Mihai-Valeriu cadmium_ Data 30 iulie 2021 18:01:49
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.69 kb
#include <fstream>
#include <vector>
#include <cstring>
#define root 0
using namespace std;

// 3 ore pierdute pe 0 puncte

ifstream cin("heavypath.in");
ofstream cout("heavypath.out");

int n;

vector<int> tree[100000];

int chainstart[100000];
int chainend[100000];
int atrchain[100000];
int atrstart[100000];

//int sumofchain[100000];

int pin[100000];
int pout[100000];
int st[100000][17];
int outpoz,inpoz;

int values[100000];

class AINT { // rip iterativ
  int aint[262144];
  public:
    void reset() {
      memset(aint,0,sizeof(aint));
    }
    void update(int val, int poz, int node=1, int cl=0, int cr=n) {
      if(cl==cr) {
        aint[node]=val;
        values[cl]=val;
        return;
      }
      int mid=(cl+cr)/2;
      if(poz<=mid)
        update(val,poz,2*node,cl,mid);
      else
        update(val,poz,2*node+1,mid+1,cr);
      aint[node]=max(aint[2*node],aint[2*node+1]);
    }
    int query(int l, int r, int node=1, int cl=0, int cr=n) {
      if(l>r)
        swap(l,r);
      //if(node!=0) {
        //cout << l << ' ' << r << ' ' << node << ' '<< cl << ' '<< cr <<' '<< aint[node] << endl;
      //}
      if(l<=cl && cr<=r) {
        return aint[node];
      }
      int mid=(cl+cr)/2,sum=0;
      if(l<=mid)
        sum=query(l,r,2*node,cl,mid);
      if(mid<r)
        sum=max(sum,query(l,r,2*node+1,mid+1,cr));
      return sum;
    }
    
} aint;

class INITHLD {
  int area[100000];
  int nchain,pinaint;
  public:
    void init() {
      aint.reset();
      
      inpoz=0;
      outpoz=0;
      initareanothers(0,0);
      
      for(int step=1; step<17; step++) {
        for(int i=0; i<n; i++) {
          st[i][step]=st[st[i][step-1]][step-1];
        }
      }
      
      nchain=-1;
      pinaint=0;
      chainstart[0]=0;
      initchain(0,0,0);
    }
    void initareanothers(int node, int father) {
      area[node]=1;
      st[node][0]=father;
      pin[node]=inpoz++;
      for(int i=0; i<tree[node].size(); i++) {
        if(tree[node][i]!=father) {
          initareanothers(tree[node][i],node);
          area[node]+=area[tree[node][i]];
        }
      }
      pout[node]=outpoz++;
    }
    void initchain(int node, int father, int continued) {
      //cout << node << ' '<< father <<endl;
      if(!continued && nchain>=0) 
        chainend[nchain]=pinaint-1;
      if(!continued) {
          nchain++;
          chainstart[nchain]=pinaint;
      }
      atrstart[node]=pinaint;
      atrchain[node]=nchain;
      aint.update(values[node],pinaint);
      pinaint++;
      int goodguy=-1;
      
      for(int i=0,child; i<tree[node].size(); i++) {
        if(tree[node][i]!=father) {
          child=tree[node][i];
          if(goodguy==-1 || area[goodguy]<area[child])
            goodguy=child;
        }
      }
      
      if(goodguy!=-1)
        initchain(goodguy,node,1);
      
      for(int i=0,child; i<tree[node].size(); i++) {
        child=tree[node][i];
        if(child!=father&& child!=goodguy)
          initchain(child,node,0);
      }
    }
} initer;

static bool isancestor(int alleged, int father) {
  return pin[alleged]>=pin[father] && pout[alleged]<=pout[father];
}

static int lca(int x, int y) {
  for(int i=16; i>=0; i--) {
    if(!isancestor(y,st[x][i]))
      x=st[x][i];
  }
  return st[x][0];
}

static int getchainsum(int from, int upto) {
  if(atrchain[from]==atrchain[upto])
    return aint.query(atrstart[upto],atrstart[from]);
  int sum=aint.query(chainstart[atrchain[from]],atrstart[from]);
  from=st[chainstart[atrchain[from]]][0];
  while(atrchain[from]!=atrchain[upto]) {
    //cout << from << '\n';
    sum=max(sum,aint.query(chainstart[atrchain[from]],from));
    from=st[chainstart[atrchain[from]]][0];
  }
  //cout << "--->" << upto << ' '<< from  <<' '<< "+"<< aint.query(atrstart[upto],atrstart[from]) <<"+" << '\n';
  
  sum=max(sum,aint.query(atrstart[upto],atrstart[from]));
  return sum;
}

static int query(int x, int y) {
  int l=lca(x,y);
  //cout << x << ' ' << l << ' '<< y << "___\n";
  int a=getchainsum(x,l),b=getchainsum(y,l);
  //cout << "___\n" << a << ' ' << b << '\n';
  return max(a,b);
}

signed main() {
  int q;
  cin >> n >> q;
  
  for(int i=0; i<n; i++) {
    cin >> values[i];
  }
  
  for(int i=1,x,y; i<n; i++) {
    cin >> x >> y;
    --x,--y;
    tree[x].push_back(y);
    tree[y].push_back(x);
  }
  
  initer.init();
  
  //for(int i=0; i<n; i++)
    //cout << atrchain[i] <<' '<< atrstart[i] <<'\n';
  
  //return 0;
  
  for(int i=0,t,x,y; i<q; i++) {
    cin >> t >> x >> y;
    --x;
    if(t==0)
      aint.update(y,atrstart[x]);
    else
      cout << query(x,y-1) << endl;
  }
  
}
/*
 * 
 * 1 2
2 3
2 7
3 4
3 5
3 6
7 8
8 9
          1
          |
          2
      /     \
     3       7
  /  |  \    |
 4   6   5   8
             |
             9
   
 */