码迷,mamicode.com
首页 > 其他好文 > 详细

SPOJ QTREE Query on a tree

时间:2015-06-05 10:20:41      阅读:125      评论:0      收藏:0      [点我收藏+]

标签:树链剖分   数据结构   

树链剖分

把边权的模板也敲了一下

关键在于弄明白点和边的对应关系

#include<stdio.h>
#include<string.h>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<math.h>
using namespace std;
#define out(x) cout<<#x<<": "<<x<<endl
const double eps(1e-8);
const int maxn=10100;
const long long inf=-1u>>1;
typedef long long ll;
int n,e[maxn][3],tot,pos;
int deep[maxn],fa[maxn],num[maxn],son[maxn];
int top[maxn],p[maxn],fp[maxn];
struct Edge{
	int v,next;
}edge[maxn<<1];
int head[maxn];
void addedge(int u,int v){
	edge[tot].v=v;
	edge[tot].next=head[u];
	head[u]=tot++;
}
void dfs1(int u,int pre,int d){//求fa、num、son和deep
	deep[u]=d;
	fa[u]=pre;
	num[u]=1;
	for(int i=head[u];i!=-1;i=edge[i].next){
		int v=edge[i].v;
		if(v==pre) continue;
		dfs1(v,u,d+1);
		num[u]+=num[v];
		if(son[u]==-1||num[v]>num[son[u]]) son[u]=v;
	}
}
void getpos(int u,int sp){//sp用于求top,并求对应位置
	top[u]=sp;
	p[u]=pos++;
	fp[p[u]]=u;
	if(son[u]==-1) return;
	getpos(son[u],sp);
	for(int i=head[u];i!=-1;i=edge[i].next){
		int v=edge[i].v;
		if(v==fa[u]||v==son[u]) continue;
		getpos(v,v);
	}
}
struct Node{
	int l,r,max;
}t[maxn<<2];
void build(int p,int l,int r){
	t[p].l=l;
	t[p].r=r;
	t[p].max=0;
	if(l==r) return;
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build((p<<1)|1,mid+1,r);
}
void update(int p,int k,int val){
	if(t[p].l==k&&k==t[p].r) {
		t[p].max=val;
		return;
	}
	int mid=(t[p].l+t[p].r)>>1;
	if(k<=mid) update(p<<1,k,val);
	else update((p<<1)|1,k,val);
	t[p].max=max(t[p<<1].max,t[(p<<1)|1].max);
}
int query(int p,int l,int r){
	if(t[p].l==l&&t[p].r==r){
		return t[p].max;
	}
	int mid=(t[p].l+t[p].r)>>1;
	if(r<=mid) return query(p*2,l,r);
	else if(l>mid) return query(p*2+1,l,r);
	else return max(query(p*2,l,mid),query(p*2+1,mid+1,r));
}
void init() {
	tot=0;
	pos=0;
	memset(son,-1,sizeof(son));
	memset(head,-1,sizeof(head));
	scanf("%d",&n);
	for(int i=0;i<n-1;i++){
		scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
		addedge(e[i][0],e[i][1]);
		addedge(e[i][1],e[i][0]);
	}
	dfs1(1,0,0);
	getpos(1,1);
	build(1,0,pos-1);
}

int find(int u,int v){
	int f1=top[u],f2=top[v];
	int tmp=0;
	while(f1!=f2){
		if(deep[f1]<deep[f2]) {
			swap(f1,f2);
			swap(u,v);
		}
		tmp=max(tmp,query(1,p[f1],p[u]));
		u=fa[f1];f1=top[u];//这里直接令u=fa[f1],所以上面查询最大值的时候可以直接用p[f1]
	}
	if(u==v) return tmp;
	if(deep[u]>deep[v]) swap(u,v);
	return max(tmp,query(1,p[son[u]],p[v]));//对每个节点来说,儿子可能有多个,但父结点只有一个,所以用一条边的下方的结点表示该边
}
int main() {
	#ifndef ONLINE_JUDGE
	//freopen("in.txt","r",stdin);
	#endif
	int T;
	scanf("%d",&T);
	while(T--){
		init();
		for(int i=0;i<n-1;i++){
			if(deep[e[i][0]]>deep[e[i][1]]) swap(e[i][0],e[i][1]);
			update(1,p[e[i][1]],e[i][2]);
		}
		char op[10];
		int a,b;
		while(scanf("%s",op)==1){
			if(op[0]=='D') break;
			scanf("%d%d",&a,&b);
			if(op[0]=='Q'){
				printf("%d\n",find(a,b));
			}
			else update(1,p[e[a-1][1]],b);//编号从0开始

		}
	}

	return 0;
}


SPOJ QTREE Query on a tree

标签:树链剖分   数据结构   

原文地址:http://blog.csdn.net/lj94093/article/details/46368235

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!