// 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();
}
}
poj 2763 Housewife Wind 边权的树链剖分
最新推荐文章于 2019-06-19 18:32:52 发布