Cod sursa(job #2241626)

Utilizator ctlin04UAIC.VlasCatalin ctlin04 Data 16 septembrie 2018 15:31:49
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.34 kb
#include<iostream>
#include<fstream>
#include<cstring>
#include<vector>
using namespace std;

struct node {
	int id;
	node *next;
}*graf[100005], *v;

int n,m;
int val[100005], subTreeSize[100005], lev[100005];
int pozInChain[100005], chainId[100005], father[100005], nrChains;
int *aint[100005];
vector<int> chain[100005];

void makeChains(int x, int l) {
	int heavyChild = -1;
	int weight = 0;
	lev[x]=l;
	
	for (node *p = graf[x]; p; p=p->next)
	 if (p->id != father[x]) {
			  father[p->id]=x;
			  makeChains(p->id,l+1);
			  subTreeSize[x]+=subTreeSize[p->id];
			  if (subTreeSize[p->id]>weight) { weight = subTreeSize[p->id]; heavyChild = p->id; }
	 }
	 
	if (heavyChild == -1) {
	   ++nrChains;
	   chain[nrChains].push_back(x);
	   pozInChain[x]=1;
	   chainId[x]=nrChains;
	}
 	else {
	  chain[chainId[heavyChild]].push_back(x);
	  pozInChain[x]=chain[chainId[heavyChild]].size();
	  chainId[x]=chainId[heavyChild];
	}
}

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

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

int queryAint(int line, int nod, int l, int r, int x, int y){
   if (l>=x && r<=y) return aint[line][nod];
   else {
	  int mid = (l+r)/2;
   	
	  int v1=0, v2=0;
	  
	  if (x<=mid) v1=queryAint(line,2*nod,l,mid,x,y);
	  if (y>mid) v2=queryAint(line,2*nod+1,mid+1,r,x,y);
	  
	  return max(v1,v2);
   }
}

int query(int x, int y) {

   if (chainId[x]==chainId[y]) {
	   return queryAint(chainId[x],1,1,chain[chainId[x]].size(),min(pozInChain[x],pozInChain[y]),max(pozInChain[x],pozInChain[y]));
   }
   else {
   	int lx = lev[father[chain[chainId[x]][chain[chainId[x]].size()-1]]];
   	int ly = lev[father[chain[chainId[y]][chain[chainId[y]].size()-1]]];
   	
   	if (lx>ly) {
	   int maxc = queryAint(chainId[x],1,1,chain[chainId[x]].size(),pozInChain[x],chain[chainId[x]].size());
	   return max(maxc,query(father[chain[chainId[x]][chain[chainId[x]].size()-1]],y));
   	}
   	else {
	   int maxc = queryAint(chainId[y],1,1,chain[chainId[y]].size(),pozInChain[y],chain[chainId[y]].size());
	   return max(maxc,query(father[chain[chainId[y]][chain[chainId[y]].size()-1]],x));
   	}
   	
   }
}

int main(void) {
	ifstream cin("heavypath.in");
	ofstream cout("heavypath.out");
	
	cin>>n>>m;
	
	for (int i=1; i<=n; ++i) cin>>val[i];
	for (int i=1; i<n; ++i) {
	  int x,y; cin>>x>>y;
		
	  v = new node(); v->id=x; v->next=graf[y]; graf[y]=v;
	  v = new node(); v->id=y; v->next=graf[x]; graf[x]=v;
	}
	
	//build chains
	makeChains(1,1);
	
	//build aint
	for (int i=1; i<=nrChains; ++i) {
	   aint[i]=new int[chain[i].size()*4+5];
	   init(i, 1, 1, chain[i].size());
	}
	
	for (int i=1; i<=m; ++i) {
	  int t, x, y;
	  cin>>t>>x>>y;
		
	  if (t==0) {
	  	val[x]=y;
	  	update(chainId[x],1,1,chain[chainId[x]].size(),x);
	  }
	  else {
	  	cout<<query(x,y)<<"\n";
	  }
	}
	
	return 0;
}