链接:http://poj.org/problem?id=2763
题意:n个点构成树,q个询问,每次询问得到树上两点距离。
操作一:问从当前位置(起始在s)到v的距离(每次移动到新的地方)。
操作二:将第i条边的长度改为w
处理出到树根的距离,操作一每次用lca求dis[s] + dis[t] - 2*dis[lca(s,t)];操作二,更新某条边之后对这条边下面的子树到树根的距离更新。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <stack>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof((a)))
#define For(i,a,b) for(int (i)=(a);(i) < (b);(i)++)
#define Ror(i,a,b) for(int (i)=(a);(i) > (b);(i)--)
#define mp make_pair
#define pb push_back
#define inf 0x3f3f3f3f
void RI (int& x){
x = 0;
char c = getchar ();
while (c == ' '||c == '\n') c = getchar ();
bool flag = 1;
if (c == '-'){
flag = 0;
c = getchar ();
}
while (c >= '0' && c <= '9'){
x = x * 10 + c - '0';
c = getchar ();
}
if (!flag) x = -x;
}
void RII (int& x, int& y){RI (x), RI (y);}
void RIII (int& x, int& y, int& z){RI (x), RI (y), RI (z);}
const int maxn = 200010;
const int maxm = 200010;
struct Side {
int v,w,next;
}side[maxm];
int top,node[maxn];
void add_side(int u,int v,int w){
side[top] = (Side){v,w,node[u]};
node[u] = top++;
}
int ver[maxn];
int r_min[maxn][20];
int first[maxn],dis[maxn],R[maxn];//R深度
int tt;
void ST(int n){
for(int i=1;i<=n;i++){
r_min[i][0]=i;
}
int k=log((double)(n+1))/log(2.0);
for(int j=1;j<=k;j++){
for(int i=1;i+(1<<j)-1<=n;i++){
int a = r_min[i][j-1],b = r_min[i+(1<<(j-1))][j-1];
r_min[i][j] = R[a] < R[b] ? a : b;
}
}
}
int RMQ(int l,int r){
int k=log((double)(r-l+1))/log(2.0);
int a = r_min[l][k],b = r_min[r-(1<<k)+1][k];
return R[a] < R[b] ? a : b;
}
int lca(int a,int b){
a = first[a];
b = first[b];
if(a > b)swap(a,b);
int ans = RMQ(a,b);
return ver[ans];
}
void dfs(int u,int dep){
ver[++ tt] = u;first[u] = tt;R[tt] = dep;
for(int i = node[u];i != -1;i = side[i].next){
int v = side[i].v;
if(first[v] == 0){
dis[v] = dis[u] + side[i].w;
dfs(v,dep+1);
ver[++ tt] = u;R[tt] = dep;
}
}
}
struct BB{
int s,t;
}bb[maxm];
void do_chg(int ss,int fa,int cc){
dis[ss] += cc;
for(int i = node[ss];i != -1;i = side[i].next){
int v = side[i].v;
if(v != fa)do_chg(v,ss,cc);
}
}
void change(int fa,int son,int w){
if(dis[fa] > dis[son])swap(fa,son);//cout<<fa<<' '<<son<<endl;
int cc;
for(int i = node[fa];i != -1;i = side[i].next){
int v = side[i].v;
if(v == son){
cc = w - side[i].w;
side[i].w = w;
break;
}
}
do_chg(son,fa,cc);
}
int main(){
//freopen("test.txt","r",stdin);
int n,q,s;
while(~scanf("%d%d%d",&n,&q,&s)){
mem(node,-1);top = 0;
For(i,0,n-1){
int a,b,c;
RIII(a,b,c);
add_side(a,b,c);
add_side(b,a,c);
bb[i+1] = (BB){a,b};
}
mem(first,0);
tt = 0;dis[1] = 0;
dfs(1,1);
ST(2*n-1);
while(q --){
int op;
RI(op);
switch(op){
case 0:{
int t;
RI(t);
cout<<dis[s] + dis[t] - 2*dis[lca(s,t)]<<endl;
//cout<<"fa:"<<lca(first[s],first[t])<<endl;
s = t;
break;
}
case 1:{
int i,w;
RII(i,w);
change(bb[i].s,bb[i].t,w);
break;
}
}
}
}
return 0;
}