Cod sursa(job #2276240)

Utilizator georgerapeanuRapeanu George georgerapeanu Data 4 noiembrie 2018 14:19:56
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.3 kb
#include <cstdio>
#include <stdexcept>
#include <algorithm>
#include <vector>

using namespace std;

FILE *f = fopen("heavypath.in","r");
FILE *g = fopen("heavypath.out","w");

class SegmentTree{
private:

	bool enforce_throws;
	int n;
	vector<int> aint;
	vector<int> lazy;
	
	void build(int nod,int st,int dr,vector<int> &base){
		lazy[nod] = 0;
		aint[nod] = 0;
		
		if(st == dr){
			aint[nod] = base[st];
			return;
		}
		
		int mid = (st + dr) / 2;
		
		build(nod * 2,st,mid,base);
		build(nod * 2 + 1,mid + 1,dr,base);
		aint[nod] = max(aint[2 * nod],aint[2 * nod + 1]);
	}
	
	void propag(int nod,int st,int dr){
		if(st == dr || !lazy[nod]){
			return;
		}
		
		lazy[2 * nod] += lazy[nod];
		lazy[2 * nod + 1] += lazy[nod];
		aint[2 * nod] += lazy[nod];
		aint[2 * nod + 1] += lazy[nod];
		lazy[nod] = 0;
	}
	
	void update(int nod,int st,int dr,int S,int D,int val){
		propag(nod,st,dr);
		
		if(D < st || S > dr){
			return ;
		}
		
		if(S <= st && dr <= D){
			lazy[nod] += val;
			aint[nod] += val;
			return ;
		}
		
		int mid = (st + dr) / 2;
		
		update(nod * 2,st,mid,S,D,val);
		update(nod * 2 + 1,mid + 1,dr,S,D,val);
		
		aint[nod] = max(aint[2 * nod],aint[2 * nod + 1]);
	}
	
	int query(int nod,int st,int dr,int S,int D){
		propag(nod,st,dr);
		
		if(D < st || S > dr){
			return -1;
		}
		
		if(S <= st && dr <= D){
			return aint[nod];
		}
		
		int mid = (st + dr) / 2;
		return max(query(nod * 2,st,mid,S,D),query(nod * 2 + 1,mid + 1,dr,S,D));
	}
	
public:
	
	SegmentTree(vector<int> &base,bool enforce_throws = true){
		this->enforce_throws = enforce_throws;
		this->n = base.size();
		aint.resize(4 * n + 1);
		lazy.resize(4 * n + 1);
		build(1,0,n - 1,base);
	}
	
	SegmentTree(int n,bool enforce_throws = true){
		this->enforce_throws = enforce_throws;
		this->n = n;
		aint.resize(4 * n + 1);
		lazy.resize(4 * n + 1);
	}
	
	void update(int st,int dr,int val){
		if(enforce_throws && (st > dr || st < 0 || dr >= n)){
			throw runtime_error("invalid update");
		}
		update(1,0,n - 1,st,dr,val);
	}
	
	int query(int st,int dr){
		if(enforce_throws && (st > dr || st < 0 || dr >= n)){
			throw runtime_error("invalid update");
		}
		
		return query(1,0,n - 1,st,dr);
	}
	
	int overall_max(){
		return aint[1];
	}
	
	void print(){
		for(auto it:aint){
			printf("%d ",it);
		}
		printf("\n");
	}
};

const int NMAX = 1e5;

int n,q;

vector<int> graph[NMAX + 5];

int id[NMAX + 5],last_id = -1;
int sz[NMAX + 5];
int head[NMAX + 5];
int pos[NMAX + 5];
vector<SegmentTree> paths;
int heavy_son[NMAX + 5];

int lvl[NMAX + 5];
int father[NMAX + 5];

int v[NMAX + 5];
int w[NMAX + 5];

void predfs(int nod,int tata){
	lvl[nod] = 1 + lvl[tata];
	w[nod] = 1;
	father[nod] = tata;
	
	for(auto it:graph[nod]){
		if(it != tata){
			predfs(it,nod);
			if(w[it] > w[heavy_son[nod]]){
				heavy_son[nod] = it;
			}
		}
	}
	
	w[tata] += w[nod];
}

void dfs(int nod,int tata){
	if(!id[nod]){
		id[nod] = ++last_id;
		head[last_id] = nod;
		pos[nod] = 0;
	}
	
	sz[id[nod]]++;
	
	for(auto it:graph[nod]){
		if(it == tata){
			continue;
		}
		
		if(it == heavy_son[nod]){
			id[it] = id[nod];
			pos[it] = pos[nod] + 1;
		}
		
		dfs(it,nod);
	}
}

int main(){
	
	fscanf(f,"%d %d",&n,&q);
	
	for(int i = 1;i <= n;i++){
		fscanf(f,"%d",&v[i]);
	}
	
	for(int i = 1;i < n;i++){
		int x,y;
		fscanf(f,"%d %d",&x,&y);
		graph[x].push_back(y);
		graph[y].push_back(x);
	}
	
	predfs(1,0);
	dfs(1,0);
	
	for(int i = 0;i <= last_id;i++){
		paths.push_back(SegmentTree(sz[i]));
	}
	
	for(int i = 1;i <= n;i++){
		paths[id[i]].update(pos[i],pos[i],v[i]);
	}

	
	while(q--){
		int c,x,y;
		fscanf(f,"%d %d %d",&c,&x,&y);
		
		if(c == 0){
			paths[id[x]].update(pos[x],pos[x],y - v[x]);
			v[x] = y;
		}

		else{
			int ans = 0;
			while(id[x] != id[y]){
				if(lvl[head[id[x]]] < lvl[head[id[y]]]){
					ans = max(ans,paths[id[y]].query(0,pos[y]));
					y = father[head[id[y]]];
				}
				else{
					ans = max(ans,paths[id[x]].query(0,pos[x]));
					x = father[head[id[x]]];
				}
			}
			
			if(pos[x] > pos[y]){
				swap(x,y);
			}
			
			ans = max(ans,paths[id[x]].query(pos[x],pos[y]));
			fprintf(g,"%d\n",ans);
		}
	}
	
	fclose(f);
	fclose(g);
	
	return 0;
}