Cod sursa(job #1760919)

Utilizator ctlin04UAIC.VlasCatalin ctlin04 Data 21 septembrie 2016 15:31:00
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.23 kb
#include<iostream>
#include<fstream>
#include<algorithm>
using namespace std;

typedef struct celula {
   int nod;	
    celula *next;
} *lista;

lista graf[100005],v,lant[100005];
int lev[100005];
int tata[100005],i,j,n,m,t,a,b,val[100005];
int heavy[100005];
int chain_poz[100005], in_chain[100005], chain_sz[100005];
int nrl;
int *aint[100005];
int aux[100005];

void build_metadata(int nod, int l) {
	
	lev[nod]=l;
	int maxh=0, heaviest=-1;
	heavy[nod]=1;
	
	for (lista p=graf[nod]; p; p=p->next)
	 if (p->nod!=tata[nod]) {
	 
	  tata[p->nod]=nod;
	  build_metadata(p->nod,l+1);
	  heavy[nod]+=heavy[p->nod];
	  
	  if (heavy[p->nod]>maxh) { maxh=heavy[p->nod]; heaviest=p->nod; }	
	 	
	 }
	 
	 if (heaviest==-1) {
	   ++nrl;
	   v=new celula; v->nod=nod; v->next=0; lant[nrl]=v;
	   in_chain[nod]=nrl;	
	   chain_sz[nrl]=1;
	 }
	 else {
	  v=new celula; v->nod=nod; v->next=lant[in_chain[heaviest]]; lant[in_chain[heaviest]]=v;	
	  in_chain[nod]=in_chain[heaviest];
	  ++chain_sz[in_chain[nod]];
	 }
	
}

void init(int nod, int l, int r, int idx) {
  
  if (l==r) aint[idx][nod]=aux[l];
  else {
      
      int mid=(l+r)/2;
      
      init(2*nod,l,mid,idx);
      init(2*nod+1,mid+1,r,idx);
      
      aint[idx][nod]=max(aint[idx][2*nod],aint[idx][2*nod+1]);
      }
	
}

void update(int idx,int nod, int l, int r, int poz, int v) {
	
  if (l==r) aint[idx][nod]=v;
  else {
    int mid=(l+r)/2;
    
    if (poz<=mid) update(idx,2*nod,l,mid,poz,v);
    else update(idx,2*nod+1,mid+1,r,poz,v);
    
    aint[idx][nod]=max(aint[idx][2*nod],aint[idx][2*nod+1]);
  
   }
	
}

int query(int idx, int nod, int l, int r, int x, int y) {
 
 
  if (l>=x && r<=y) return aint[idx][nod];
  else {
    int mid=(l+r)/2;
	
	int vl=0, vr=0;
	
	if (x<=mid)	vl=query(idx,2*nod,l,mid,x,y);
	if (y>mid) vr=query(idx,2*nod+1,mid+1,r,x,y);
	
	return max(vl,vr);
  }
	
}

int getMax(int x, int y) {
	
  int sol=0;
	
  while (in_chain[x]!=in_chain[y]) {
    
    if (lev[lant[in_chain[x]]->nod]<lev[lant[in_chain[y]]->nod]) swap(x,y);
    
    sol=max(sol,query(in_chain[x],1,1,chain_sz[in_chain[x]],1,chain_poz[x]));
    x=tata[lant[in_chain[x]]->nod];
  
   }
   
   if (chain_poz[x]>chain_poz[y]) swap(x,y);
   
   return max(sol,query(in_chain[x],1,1,chain_sz[in_chain[x]],chain_poz[x],chain_poz[y]));
	
}

int main(void) {
	
	ifstream cin("heavypath.in");
	ofstream cout("heavypath.out");
	
	cin>>n>>m;
	for (i=1; i<=n; ++i) cin>>val[i];
	
	for (i=1; i<n; ++i) {
	   int x,y;
	   cin>>x>>y;
	   v=new celula; v->nod=x; v->next=graf[y]; graf[y]=v;
	   v=new celula; v->nod=y; v->next=graf[x]; graf[x]=v;
	}
	
	build_metadata(1,1);
	
	//build aints
	for (i=1; i<=nrl; ++i) {
	
	 aint[i]=new int[4*chain_sz[i]+4];
	 int j=1;
	 
	 for (lista p=lant[i]; p; p=p->next, ++j){
	    chain_poz[p->nod]=j;	
	 	aux[j]=val[p->nod];
	 }
	 
	 init(1,1,chain_sz[i],i);	
		
	}
	
	//run queries
	
	for (i=1; i<=m; ++i) {
	
    	int op, x,y;
    	
    	cin>>op>>x>>y;
    	
    	if (op==0) {
    	  val[x]=y;	
    	  update(in_chain[x],1,1,chain_sz[in_chain[x]],chain_poz[x],y);	
    	}
    	else {
    	
		cout<<getMax(x,y)<<"\n";	
    		
    	}
		
	}
	
	return 0;
}