poj3237Tree【树链刨分】



Language:
Tree
Time Limit: 5000MS Memory Limit: 131072K
Total Submissions: 6574 Accepted: 1800

Description

You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:

CHANGE i vChange the weight of the ith edge to v
NEGATE a bNegate the weight of every edge on the path from a to b
QUERY a bFind the maximum weight of edges on the path from a to b

Input

The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.

Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N − 1 lines each contains three integers ab and c, describing an edge connecting nodes a and b with weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “DONE” ends the test case.

Output

For each “QUERY” instruction, output the result on a separate line.

Sample Input

1

3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE

Sample Output

1
3

Source


题意:同spoj375比他多一个线段树区间更新

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int maxn=50010;
struct Node{
	int to,next;
}A[maxn<<1];
int MAX(int a,int b){
	return a>b?a:b;
}
int edge,root,N,totw,d[maxn][3],fa[maxn];
int head[maxn],size[maxn],tree[maxn<<2];
int dep[maxn],pos[maxn],top[maxn],son[maxn];
void init(){
	edge=totw=0;
	memset(fa,0,sizeof(fa));
	memset(dep,0,sizeof(dep));
	memset(size,0,sizeof(size));
	memset(head,-1,sizeof(head));
	memset(tree,0,sizeof(tree));
}
void insert(int a,int b){
	A[edge].to=b;
	A[edge].next=head[a];
	head[a]=edge++;
}
void dfs(int v){
	size[v]=1;son[v]=0;
	for(int k=head[v];k!=-1;k=A[k].next){
		if(A[k].to!=fa[v]){
			fa[A[k].to]=v;
			dep[A[k].to]=dep[v]+1;
			dfs(A[k].to);
			size[v]+=size[A[k].to];
			if(size[A[k].to]>size[son[v]])son[v]=A[k].to;
		}
	}
}
void buildtree(int v,int tp){
	int k;pos[v]=++totw;top[v]=tp;
	if(son[v])buildtree(son[v],top[v]);
	for(int k=head[v];k!=-1;k=A[k].next){
		if(A[k].to!=fa[v]&&A[k].to!=son[v]){
			buildtree(A[k].to,A[k].to);
		}
	}
}
void change(int p,int x,int l,int r,int rt){
	if(p>r||p<l)return ;
	if(l==r){
		tree[rt]=x;
		return ;
	}
	int mid=(l+r)>>1;
	change(p,x,lson);
	change(p,x,rson);
	tree[rt]=MAX(tree[rt<<1],tree[rt<<1|1]);
}
void Negate(int ll,int rr,int l,int r,int rt){
	if(l==r){
		tree[rt]*=-1;
		return ;
	}
	int mid=(l+r)>>1;
	if(ll<=mid)Negate(ll,rr,lson);
	if(rr>mid)Negate(ll,rr,rson);
	tree[rt]=MAX(tree[rt<<1],tree[rt<<1|1]);
}
void negate(int va,int vb){
	int f1=top[va],f2=top[vb];
	while(f1!=f2){
		if(dep[f1]<dep[f2]){
			swap(va,vb);
			swap(f1,f2);
		}
		Negate(pos[f1],pos[va],1,totw,1);
		va=fa[f1];f1=top[va];
	}
	if(dep[va]>dep[vb])swap(va,vb);
	Negate(pos[son[va]],pos[vb],1,totw,1);
}
int maxi(int ll,int rr,int l,int r,int rt){
	if(ll>r||rr<l)return -inf;
	if(l>=ll&&r<=rr){
		return tree[rt];
	}
	int mid=(l+r)>>1;
	return MAX(maxi(ll,rr,lson),maxi(ll,rr,rson));
}
int find(int va,int vb){
	int f1=top[va],f2=top[vb],tmp=-inf;
	while(f1!=f2){
		if(dep[f1]<dep[f2]){
			swap(va,vb);
			swap(f1,f2);
		}
		tmp=MAX(tmp,maxi(pos[f1],pos[va],1,totw,1));
		va=fa[f1];f1=top[va];
	}
	if(va==vb)return tmp;
	if(dep[va]>dep[vb])swap(va,vb);
	return MAX(tmp,maxi(pos[son[va]],pos[vb],1,totw,1));
}
int main()
{
	int n,m,q,t;
	char str[10];
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		int a,b,c;init();
		for(int i=1;i<n;++i){
			scanf("%d%d%d",&d[i][0],&d[i][1],&d[i][2]);
			insert(d[i][0],d[i][1]);
			insert(d[i][1],d[i][0]);
		}
		dfs(1);
		buildtree(1,1);
		for(int i=1;i<n;++i){
			if(dep[d[i][0]]>dep[d[i][1]])swap(d[i][0],d[i][1]);
			change(pos[d[i][1]],d[i][2],1,totw,1);
		}
		while(scanf("%s",str),str[0]!='D'){
			if(str[0]=='Q'){
				scanf("%d%d",&a,&b);
				printf("%d\n",find(a,b));
			}
			else if(str[0]=='N'){
				scanf("%d%d",&a,&b);
				negate(a,b);	
			}
			else if(str[0]=='C'){
				scanf("%d%d",&a,&b);
				change(pos[d[a][1]],b,1,totw,1);
			}
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值