poj 2763 Housewife Wind 边权的树链剖分

23 篇文章 0 订阅
4 篇文章 0 订阅
//	poj 2763 Housewife Wind 边权的树链剖分
//	
//	题目意思很清楚,关于边权的树链剖分,首先
//	肯定是先把链剖分好啦,然后就是将边权转化
//	成离根节点较远的点的权值即可.单点更新,
//	区间求和,注意,莫要重复计算哟,这题还有需要
//	研究的地方,继续加油吧~~~
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define cls(x,a) memset(x,(a),sizeof(x))
using namespace std;

const int maxn = 100000 + 8;
int n,q,s;

int head[maxn];

int id;
int idx[maxn];
int father[maxn];
int siz[maxn];
int son[maxn];
int dep[maxn];
int rk[maxn];
int top[maxn];

int num;

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

	}

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

	}
}edges[maxn<<1];

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


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

	}
	edge(int u,int v,int w):u(u),v(v),w(w){

	}
}e[maxn];


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

	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);
	}
}

#define lson(x) (x<<1)
#define rson(x) (x<<1|1)

int seg[maxn<<2];
int val[maxn];

void push_up(int ro){
	seg[ro] = seg[lson(ro)] + seg[rson(ro)];
}

void build(int ro,int L,int R){
	if (L == R){
		seg[ro] = val[L];
		return ;
	}

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

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

int ql,qr,delta;

void update(int ro,int L,int R){
	if (L == R){
		seg[ro] = delta;
		return ;
	}

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

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

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

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

	int ans = 0;

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

int get(int u,int v){
	int p = top[u],q = top[v];
	
	int ans = 0;

	while(p != q){
		if (dep[p] < dep[q]){
			swap(u,v);
			swap(p,q);
		}
	
		ql = idx[p];
		qr = idx[u];

		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 += query(1,1,n);

	return ans;
}

void input(){
	cls(head,-1);
	num = 0;
	id = 1;
	for (int i=1;i<n;i++){
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		e[i] = edge(u,v,w);
		add_edges(u,v);
		add_edges(v,u);
	}
	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);
	for (int i=1;i<=q;i++){
		int k,u,v;
		scanf("%d",&k);
		if (k==0){
			scanf("%d",&u);
			printf("%d\n",get(s,u));
			s = u;
		}else {
			scanf("%d%d",&u,&v);
			ql = idx[e[u].u];
			delta = v;
			update(1,1,n);
		}
	}

}

int main(){
	//freopen("1.txt","r",stdin);
	while(scanf("%d%d%d",&n,&q,&s)!=EOF){
		input();
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值