一个64位的数,最多在被大于1的数整除64次后就变为0
所以对于每次访问,我们最多除64次
那么我们就要将为1的路压缩,使用并查集
每次访问使用lca,找到公共祖先lc,然后u->lc,v->lc,访问这两条路
记得并查集的时候要用
return par[u] == u ? u : par[u] = find(par[u]);
不要用
return par[u] == u ? u : find(par[u]);
后者也能查询,但是前者再并在一起省时,不然会t的
/********************************************
Author :Crystal
Created Time :
File Name :
********************************************/
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <climits>
#include <string>
#include <vector>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <cctype>
using namespace std;
typedef long long ll;
typedef pair<int ,int> pii;
#define MEM(a,b) memset(a,b,sizeof a)
#define CLR(a) memset(a,0,sizeof a);
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
//#define LOCAL
#define maxn 500005
int root = 1;
int head[maxn],nxt[maxn],pnt[maxn];
int par[maxn];
ll cost[maxn];
int dep[maxn],far[maxn],p[maxn][30];
ll path[maxn][30];
int dis[maxn];
int u[maxn];
int v[maxn];
ll c[maxn];
int cnt = 0;
int n,q;
int find(int u){
return par[u] == u ? u : par[u] = find(par[u]);
}
void addedge(int u,int v,ll c){
pnt[cnt] = v;
nxt[cnt] = head[u];
cost[cnt] = c;
head[u] = cnt++;
}
int llog = 20;
void dfs(int u,int f,int d){
dep[u] = d;
p[u][0] = f;
for(int i=head[u];~i;i = nxt[i]){
int v = pnt[i];
if(v == f)continue;
path[v][0] = cost[i];
dfs(v, u, d+1);
}
}
void init(){
dfs(root, -1, 0);
for(int i=0;i+1<llog;i++){
for(int v=1;v<=n;v++){
if(p[v][i] == -1)p[v][i+1] = -1;
else p[v][i+1] = p[p[v][i]][i];
}
}
}
int lca(int u,int v){
if(dep[u] > dep[v])swap(u,v);
for(int i=0;i<llog;i++){
if(dep[v]-dep[u] >> i & 1){
v = p[v][i];
}
}
if(u == v)return u;
for(int i=llog - 1;i != -1;i--){
if(p[u][i] != p[v][i]){
u = p[u][i];
v = p[v][i];
}
}
return p[u][0];
}
ll solve(int u,int v,ll x){
//cout << u <<v <<x << endl;
int cnt = 0;
while(x && dep[u] < dep[v] && cnt < 65){
v = find(v);
if(dep[u] >= dep[v])break;
x /= path[v][0];
v = p[v][0];
cnt++;
}
return x;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
cin >> n >> q;
MEM(head,-1);
for(int i=1;i<n;i++){
scanf("%d%d%lld",&u[i],&v[i],&c[i]);
addedge(u[i],v[i],c[i]);
addedge(v[i],u[i],c[i]);
}
for(int i=1;i<=n;i++)par[i] = i;
init();
for(int i=1;i<n;i++){
if(c[i]==1){
if(dep[u[i]] > dep[v[i]]){
par[u[i]] = find(v[i]);
}
else{
par[v[i]] = find(u[i]);
}
}
}
for(int i=1;i<=q;i++){
int f;cin >> f;
if(f==1){
int u,v;
ll x;
scanf("%d%d%lld",&u,&v,&x);
int lc = lca(u,v);
//cout << lc << endl;
x = solve(lc,u,x);
x = solve(lc,v,x);
printf("%lld\n",x);
}
else{
int load;
ll x;scanf("%d%lld",&load,&x);
int a = u[load];
int b = v[load];
if(dep[a]>dep[b]){
path[a][0] = x;
}
else{
path[b][0] = x;
}
if(x == 1){
if(dep[a]>dep[b]){
par[a] = find(b);
}
else par[b] = find(a);
}
}
}
return 0;
}