/*
题意:有一颗树,每条边有边权
有两个操作:
1、给出一个点x,求当前点s和点x所在的路径上的边的边权之和(然后s=x)。
2、给出一个边i和一个值val,把第i条边的边权修改为val。
节点数 1e5 操作数1e5 边权1e4 val ≤ 1e4
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100000+10;
int N,Q,S;
int edge_cnt,tot;
int value[maxn],head[maxn];
struct Path{
int to,next;
}edge[maxn<<1];
void ADD(int u,int v){
edge[edge_cnt].to = v;
edge[edge_cnt].next = head[u];
head[u] = edge_cnt++;
}
struct path{
int x,y,val;
void read(){
scanf("%d %d %d",&x,&y,&val);
}
}PATH[maxn];
int size[maxn],son[maxn],fa[maxn],deep[maxn];
void dfs1(int now,int father,int Deep){
size[now] = 1;
fa[now] = father;
deep[now] = Deep;
son[now] = 0;
for(int i = head[now]; ~i; i = edge[i].next){
int v = edge[i].to;
if(v != father){
dfs1(v,now,Deep+1);
size[now] += size[v];
if(size[son[now]] < size[v])
son[now] = v;
}
}
}
int id[maxn],top[maxn],Rank[maxn];
void dfs2(int now,int Top){
id[now] = ++tot;
top[now] = Top;
Rank[id[now]] = now;
if(son[now])
dfs2(son[now],Top);
for(int i = head[now]; ~i; i = edge[i].next){
int v = edge[i].to;
if(v != fa[now] && v != son[now])
dfs2(v,v);
}
}
struct Info{
int sum;
int l,r;
};
struct SGT{
Info tree[maxn<<2];
void pushUp(int now){
tree[now].sum = tree[now<<1].sum+tree[now<<1|1].sum;
}
void build(int now,int l,int r){
tree[now].l = l;
tree[now].r = r;
if(l == r){
tree[now].sum = value[Rank[l]];
return;
}
int Mid = (l+r)>>1;
build(now<<1,l,Mid);
build(now<<1|1,Mid+1,r);
pushUp(now);
}
void update(int now,int idx,int val){
if(tree[now].l == tree[now].r){
tree[now].sum = val;
return;
}
int Mid = (tree[now].l+tree[now].r)>>1;
if(idx <= Mid)
update(now<<1,idx,val);
else
update(now<<1|1,idx,val);
pushUp(now);
}
int query(int now,int l,int r){
if(l <= tree[now].l && tree[now].r <= r){
return tree[now].sum;
}
int ans = 0;
int Mid = (tree[now].l+tree[now].r)>>1;
if(l <= Mid)
ans += query(now<<1,l,r);
if(Mid < r)
ans += query(now<<1|1,l,r);
return ans;
}
};
SGT sgt;
int work(int s,int e){
int tps = top[s];
int tpe = top[e];
int ans = 0;
while(tps != tpe){
if(deep[tps]<deep[tpe]){
swap(s,e);
swap(tps,tpe);
}
ans += sgt.query(1,id[tps],id[s]);
s = fa[tps];
tps = top[s];
}
if(s == e)return ans;//如果在同一个点上没有时间耗费
if(deep[s] > deep[e]){
swap(s,e);
}
ans += sgt.query(1,id[son[s]],id[e]);
return ans;
}
int main(){
while(~scanf("%d %d %d",&N,&Q,&S)){
memset(head,-1,sizeof(head));
edge_cnt = tot = 0;
for(int i = 1; i < N; i++){
PATH[i].read();
ADD(PATH[i].x,PATH[i].y);
ADD(PATH[i].y,PATH[i].x);
}
dfs1(1,0,1);
dfs2(1,1);
value[1] = 0;
//因为点没有点权,只有边有,要把边权转化成点权。
//把每条边的边权赋给,在id小的那个节点。
for(int i = 1; i < N; i++){
if(deep[PATH[i].x] < deep[PATH[i].y])
swap(PATH[i].x,PATH[i].y);
value[PATH[i].x] = PATH[i].val;
}
sgt.build(1,1,N);
int op,u,v;
while(Q--){
scanf("%d",&op);
if(op){
scanf("%d %d",&u,&v);
sgt.update(1,id[PATH[u].x],v);
}
else{
scanf("%d",&u);
printf("%d\n",work(S,u));
S = u;
}
}
}
return 0;
}
POJ2763
最新推荐文章于 2022-03-20 20:00:07 发布