Alice 和 Bob 在玩一个游戏。
游戏在一棵有 n 个点的树上进行。最初,每个点上都只有一个数字,那个数字是 123456789123456789。
有时,Alice 会选择一条从 s 到 t 的路径,在这条路径上的每一个点上都添加一个数字。对于路径上的一个点 r,
若 r 与 s 的距离是 dis,那么 Alice 在点 r 上添加的数字是 a×dis+b。有时,Bob 会选择一条从 s 到 t 的路径。
他需要先从这条路径上选择一个点,再从那个点上选择一个数字。
Bob 选择的数字越小越好,但大量的数字让 Bob 眼花缭乱。Bob 需要你帮他找出他能够选择的最小的数字。
第一行两个数字 n、m,表示树的点数和进行的操作数。
接下来 n−1 行,每行三个数字 u、v、w,表示树上有一条连接 u、v 的边,长度是 w。
接下来 m 行。每行第一个数字是 1 或 2。
若第一个数是 1,表示 Alice 进行操作,接下来四个数字 s、t、a、b。
若第一个数是 2,表示 Bob 进行操作,接下来四个数字 s、t。
1 #include <iostream>
2 #include <cstring>
3 #include <cstdio>
4 using namespace std;
5 const int maxn=100010;
6 const long long INF=123456789123456789LL;
7 int cnt,fir[maxn],nxt[maxn<<1],to[maxn<<1],val[maxn<<1];
8 void addedge(int a,int b,int v){
9 nxt[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;val[cnt]=v;
10 }
11
12 int ID[maxn],top[maxn],rID[maxn],tot,n,Q;
13 int sz[maxn],dep[maxn],fa[maxn],son[maxn];
14 long long dis[maxn],Min[maxn<<2];
15
16 void DFS(int x){
17 sz[x]=1;
18 for(int i=fir[x];i;i=nxt[i])
19 if(to[i]!=fa[x]){
20 fa[to[i]]=x;
21 dep[to[i]]=dep[x]+1;
22 dis[to[i]]=dis[x]+val[i];
23 DFS(to[i]);
24 sz[x]+=sz[to[i]];
25 if(sz[son[x]]<sz[to[i]])
26 son[x]=to[i];
27 }
28 }
29
30 void DFS(int x,int tp){
31 top[x]=tp;
32 ID[x]=++tot;rID[tot]=x;
33 if(son[x])DFS(son[x],tp);
34 for(int i=fir[x];i;i=nxt[i])
35 if(to[i]!=fa[x]&&to[i]!=son[x])
36 DFS(to[i],to[i]);
37 }
38
39 int Lca(int x,int y){
40 while(top[x]!=top[y]){
41 if(dep[top[x]]<dep[top[y]])swap(x,y);
42 x=fa[top[x]];
43 }
44 return dep[x]<dep[y]?x:y;
45 }
46
47 void Build(int x,int l,int r){
48 Min[x]=INF;
49 if(l==r)return;
50 int mid=(l+r)>>1;
51 Build(x<<1,l,mid);
52 Build(x<<1|1,mid+1,r);
53 }
54
55 struct Node{
56 long long a,b;
57 Node(long long a_=0,long long b_=INF){
58 a=a_;b=b_;
59 }
60 long long Val(int x){
61 return a*dis[rID[x]]+b;
62 }
63 }T[maxn<<2];
64
65 int CmP(int l,int r,Node x,Node y){
66 if(x.Val(l)<=y.Val(l)&&x.Val(r)<=y.Val(r))return 1;
67 if(x.Val(l)>=y.Val(l)&&x.Val(r)>=y.Val(r))return -1;
68 return 0;
69 }
70
71 void Update(int x,int l,int r,int a,int b,Node p){
72 if(l>b||r<a)return;
73 Min[x]=min(Min[x],min(p.Val(max(l,a)),p.Val(min(r,b))));
74 int mid=(l+r)>>1;
75 if(l>=a&&r<=b){
76 int tmp=CmP(l,r,p,T[x]);
77 if(tmp==1)T[x]=p;
78 if(tmp!=0)return;//这里可以不用判断l==r
79
80 tmp=CmP(l,mid,p,T[x]);
81 if(tmp!=1)Update(x<<1,l,mid,a,b,T[x]);
82 tmp=CmP(mid+1,r,p,T[x]);
83 if(tmp!=1)Update(x<<1|1,mid+1,r,a,b,T[x]);
84 }
85 Update(x<<1,l,mid,a,b,p);
86 Update(x<<1|1,mid+1,r,a,b,p);
87 }
88
89 void Modify(int x,int y,Node p){
90 while(top[x]!=top[y]){
91 Update(1,1,n,ID[top[x]],ID[x],p);
92 x=fa[top[x]];
93 }
94 Update(1,1,n,ID[y],ID[x],p);
95 }
96
97 long long Query(int x,int l,int r,int a,int b){
98 if(l>b||r<a)return INF;
99 if(l>=a&&r<=b)return Min[x];
100 int mid=(l+r)>>1;
101 long long ret=min(T[x].Val(max(l,a)),T[x].Val(min(r,b)));
102 if(mid>=a)ret=min(ret,Query(x<<1,l,mid,a,b));
103 if(mid<b)ret=min(ret,Query(x<<1|1,mid+1,r,a,b));
104 return ret;
105 }
106
107 long long Solve(int x,int y){
108 long long ret=INF;
109 while(top[x]!=top[y]){
110 if(dep[top[x]]<dep[top[y]])swap(x,y);
111 ret=min(ret,Query(1,1,n,ID[top[x]],ID[x]));
112 x=fa[top[x]];
113 }
114 if(dep[x]<dep[y])swap(x,y);
115 ret=min(ret,Query(1,1,n,ID[y],ID[x]));
116 return ret;
117 }
118
119 int main(){
120 #ifndef ONLINE_JUDGE
121 freopen("menci_game.in","r",stdin);
122 freopen("menci_game.out","w",stdout);
123 #endif
124 scanf("%d%d",&n,&Q);
125 for(int i=1,u,v,w;i<n;i++){
126 scanf("%d%d%d",&u,&v,&w);
127 addedge(u,v,w);addedge(v,u,w);
128 }
129 DFS(1);
130 DFS(1,1);
131 Build(1,1,n);
132
133 int type,s,t,lca;
134 long long a,b;
135 while(Q--){
136 scanf("%d",&type);
137 if(type==1){
138 scanf("%d%d%lld%lld",&s,&t,&a,&b);
139 lca=Lca(s,t);
140 Modify(s,lca,Node(-a,a*dis[s]+b));
141 Modify(t,lca,Node(a,a*(dis[s]-2*dis[lca])+b));
142 }
143 else{
144 scanf("%d%d",&s,&t);
145 printf("%lld\n",Solve(s,t));
146 }
147 }
148 return 0;
149 }