您的位置:首页 > 其它

poj 3237 Tree 树链剖分

2015-09-19 23:58 127 查看
//	poj 3237 Tree  树链剖分
//
//	解题思路:
//		
//		树链剖分,维护一个最大值和一个最小值,
//	区间更新,laz标记.单点更新,去掉叶子节点的laz
//	标记.边权改为离根节点较远的点的点权.求lca
//	的方式进行区间更新.注意线段树的操作以及push_up()
//	push_down()的操作.写了很久,感悟颇多,继续加油吧~~~

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define cls(x,a)	memset(x,a,sizeof(x))
using namespace std;

const int MAXN = 10008;
const int INF = 0x7fffffff;
int n;

int num;
int id;
int idx[MAXN];	// 树上节点在线段树中的编号
int son[MAXN];  // 重儿子
int siz[MAXN];  // 以该节点为根的子树的节点数
int dep[MAXN];  // 节点的深度
int top[MAXN];  // 链的开头
int rk[MAXN];   // 与idx互逆的
int father[MAXN]; // 父节点

int head[MAXN];

int val[MAXN];

struct adj{
	int to;
	int next;
	
	adj(){

	}

	adj(int a,int b):to(a),next(b){

	}

}edges[MAXN<<1];

struct node {
	int u;
	int v;
	int w;
	node(){

	}

	node(int u,int v,int w):u(u),v(v),w(w){

	}

}e[MAXN];

void add_edge(int u,int v){
	edges[num] = adj(v,head[u]);
	head[u] = num++;
}

void dfs(int u,int fa,int d){ 
	dep[u] = d;
	father[u] =fa;
	son[u] = 0;
	siz[u] = 1;

	for (int i = head[u]; i + 1; i = edges[i].next){
		int v = edges[i].to;
		if (v == fa)
			continue;
		dfs(v,u,d+1);
		siz[u] += siz[v];
		if (siz[son[u]] < siz[v])
			son[u] = v;
	}
}

void dfs(int u,int tp){
	top[u] = tp;
	idx[u] = id++;
	rk[idx[u]] = u;
	if (son[u])	dfs(son[u],tp);

	for (int i = head[u] ;i + 1 ;i = edges[i].next){
		int v = edges[i].to;
		if (v == father[u] || v == son[u])
			continue;
		dfs(v,v);
	}
}

void input(){
	id = 1;
	num = 0;
	cls(idx,0);
	cls(father,0);
	cls(son,0);
	cls(head,-1);
	scanf("%d",&n);
	for (int i = 1;i < n;i ++){
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		e[i] = node(u,v,w);
		add_edge(u,v);
		add_edge(v,u);
	}
}

#define lson(x)	(x<<1)  // 线段树部分
#define rson(x)	(x<<1|1)
int vmax[MAXN<<2];
int vmin[MAXN<<2];
int laz[MAXN<<2];
int ql,qr;
int delta;

inline void update_node(int ro){
	vmax[ro] *= -1;
	vmin[ro] *= -1;
	swap(vmin[ro],vmax[ro]);
}

inline void push_up(int ro){
	vmax[ro] = max(vmax[lson(ro)],vmax[rson(ro)]);
	vmin[ro] = min(vmin[lson(ro)],vmin[rson(ro)]);
}

inline void push_down(int ro,int L,int R){
	if (L == R)	return;
	if (laz[ro]){

		laz[lson(ro)] ^= 1;
		laz[rson(ro)] ^= 1;
		update_node(lson(ro));
		update_node(rson(ro));
		laz[ro] = 0;
	}
}

void build(int ro,int L,int R){
	laz[ro] = 0;
	if (L == R){
		vmax[ro] = val[L];
		vmin[ro] = val[L];
		return ;
	}

	int M = (L + R) >> 1;

	build(lson(ro),L,M);
	build(rson(ro),M+1,R);
	push_up(ro);
}

void n_update(int ro,int L,int R){
	if (ql<= L && R <= qr){
		laz[ro] ^= 1;
		update_node(ro);
		return ;
	}
	push_down(ro,L,R);

	int M = (L + R) >> 1;

	if (ql <= M )	n_update(lson(ro),L,M);
	if (M < qr)	n_update(rson(ro),M+1,R);
	push_up(ro);
}

void c_update(int ro,int L,int R){
	if (L == R){
		vmax[ro] = delta;
		vmin[ro] = delta;
		laz[ro] = 0;
		return ;
	}
	
	push_down(ro,L,R);

	int M = (L + R) >> 1;

	if (ql <= M)	c_update(lson(ro),L,M);
	else	c_update(rson(ro),M+1,R);
	push_up(ro);

}

int query(int ro,int L,int R){
	if (ql <= L && R <= qr){
		return vmax[ro];
	}
	
	push_down(ro,L,R);

	int M = (L + R) >> 1;
	int ans = -INF;
	if (ql <= M)	ans = max(ans,query(lson(ro),L,M));
	if (M < qr)	ans = max(ans,query(rson(ro),M+1,R));
	return ans;	
}

void split(){

	dfs(1,0,0);
	dfs(1,1);

	for (int i = 1;i < n;i ++){
		
		if (dep[e[i].u] < dep[e[i].v])
			swap(e[i].u,e[i].v);
		
		val[idx[e[i].u]] = e[i].w;
	}
	build(1,1,n);
}

void Negate(int u,int v){
	int p = top[u], q = top[v];
	int ans = INF;
	while(p!=q){
		if (dep[p] < dep[q]){
			swap(p,q);
			swap(u,v);
		}
		ql = idx[p];
		qr = idx[u];
		
		n_update(1,1,n);

		u = father[p];
		p = top[u];

	}
	
	if (u == v)
		return;

	if (dep[u] > dep[v])
		swap(u,v);

	ql = idx[son[u]];
	qr = idx[v];
	n_update(1,1,n);
}

int get_max(int u,int v){
	int p = top[u], q = top[v];
	int ans = -INF;
	while(p!=q){
		if (dep[p] < dep[q]){
			swap(p,q);
			swap(u,v);
		}
		ql = idx[p];
		qr = idx[u];
		ans = max(ans,query(1,1,n));
		u = father[p];
		p = top[u];

	}
	
	if (u == v)
		return ans;

	if (dep[u] > dep[v])
		swap(u,v);
	ql = idx[son[u]];
	qr = idx[v];
	ans = max(ans,query(1,1,n));
	return ans;

}

void solve(){
	char s[20];
	while(1){
		scanf("%s",s);
		if (s[0] == 'D')
			break;
		else if (s[0] == 'Q'){
			int u,v;
			scanf("%d%d",&u,&v);
			printf("%d\n",get_max(u,v));
		}else if (s[0] == 'C'){
			int i,v;
			scanf("%d%d",&i,&v);
			ql = idx[e[i].u];
			delta = v;
			c_update(1,1,n);
		}else {
			int u,v;
			scanf("%d%d",&u,&v);
			Negate(u,v);
		}

	}
}

int main(){
	int t;
	//freopen("1.txt","r",stdin);
	scanf("%d",&t);
	while(t--){
		input();
		split();
		solve();
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: