SPOJ-QTREE Query on a tree 树链剖分

欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - SPOJ-QTREE


题意概括

  给你一颗树,每两点之间有权值,然后改变一些权值,问一条路径上的最大值。


题解

  树链剖分裸题。


代码

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstdlib>
using namespace std;
const int N=10005;
struct Edge{
	int cnt,y[N*2],z[N*2],nxt[N*2],fst[N];
	void clear(){
		cnt=0;
		memset(fst,0,sizeof fst);
	}
	void add(int a,int b,int c){
		y[++cnt]=b,z[cnt]=c,nxt[cnt]=fst[a],fst[a]=cnt;
	}
}g;
struct edge{
	int a,b,c;
}e[N];
int T,n,pos;
int fa[N],fadis[N],size[N],depth[N],son[N],top[N],p[N],ap[N];
int maxv[N*4];
void Get_Gen_Info(int rt,int pre,int d){
	depth[rt]=d,fa[rt]=pre,size[rt]=1,son[rt]=-1;
	for (int i=g.fst[rt];i;i=g.nxt[i])
		if (g.y[i]!=pre){
			int s=g.y[i];
			fadis[s]=g.z[i];
			Get_Gen_Info(s,rt,d+1);
			size[rt]+=size[s];
			if (son[rt]==-1||size[s]>size[son[rt]])
				son[rt]=s;
		}
}
void Get_Pos(int rt,int tp){
	top[rt]=tp;
	if (son[rt]==-1){
		p[rt]=++pos,ap[pos]=rt;
		return;
	}
	else {
		p[rt]=++pos,ap[pos]=rt;
		Get_Pos(son[rt],tp);
	}
	for (int i=g.fst[rt];i;i=g.nxt[i]){
		int s=g.y[i];
		if (s!=fa[rt]&&s!=son[rt])
			Get_Pos(s,s);
	}
}
void pushup(int rt){
	maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);
}
void build(int rt,int le,int ri){
	if (le==ri){
		maxv[rt]=fadis[ap[le]];
		return;
	}
	int mid=(le+ri)>>1;
	build(rt<<1,le,mid);
	build(rt<<1|1,mid+1,ri);
	pushup(rt);
}
void change(int rt,int le,int ri,int pos,int v){
	if (le==ri){
		maxv[rt]=v;
		return;
	}
	int mid=(le+ri)>>1;
	if (pos<=mid)
		change(rt<<1,le,mid,pos,v);
	else
		change(rt<<1|1,mid+1,ri,pos,v);
	pushup(rt);
}
int query(int rt,int le,int ri,int xle,int xri){
	if (ri<xle||le>xri)
		return 0;
	if (xle<=le&&ri<=xri)
		return maxv[rt];
	int mid=(le+ri)>>1;
	return max(query(rt<<1,le,mid,xle,xri),query(rt<<1|1,mid+1,ri,xle,xri));
}
int find(int a,int b){
	int f1=top[a],f2=top[b],ans=0;
	while (f1!=f2){
		if (depth[f1]<depth[f2])
			swap(f1,f2),swap(a,b);
		ans=max(ans,query(1,1,n,p[f1],p[a]));
		a=fa[f1],f1=top[a];
	}
	if (a==b)
		return ans;
	if (depth[a]>depth[b])
		swap(a,b);
	return max(ans,query(1,1,n,p[son[a]],p[b]));
}
int main(){
	scanf("%d",&T);
	while (T--){
		g.clear();
		scanf("%d",&n);
		for (int i=1,a,b,c;i<n;i++){
			scanf("%d%d%d",&a,&b,&c);
			e[i].a=a,e[i].b=b,e[i].c=c;
			g.add(a,b,c);
			g.add(b,a,c);
		}
		pos=0,fadis[1]=0;
		Get_Gen_Info(1,0,0);
		Get_Pos(1,1);
		for (int i=1;i<n;i++)
			if (depth[e[i].a]>depth[e[i].b])
				swap(e[i].a,e[i].b);
		build(1,1,n);
		char str[10];
		while (scanf("%s",str)){
			if (str[0]=='D')
				break;
			int a,b;
			scanf("%d%d",&a,&b);
			if (str[0]=='Q')
				printf("%d
",find(a,b));
			else
				change(1,1,n,p[e[a].b],b);
		}
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/zhouzhendong/p/SPOJ-QTREE.html