Jzoj4846 行走
这个题一看就是树剖的模型
但是有一些问题,比如权值的乘机太大了,可能会爆long long
一种解决的方法:我们考虑到,v<=10^18 所以最多经过60条大于1的边
对于权值为1的边我们可以用一个并查集合并(注意只会改小)
但是这种方法不好想,我们还是考虑树剖
若权值>=10^18 我们可以直接将其变为一个特殊的值(例如-1)表示“足够大”,这种情况直接输出0
若不够,我们有一个结论: [[a/b]/c] = [a/bc] 这个是显然的,所以可以将路径上的权值乘机求出并直接得到答案
CODE比较长但是比较好想(mul()这里做乘法的时候会爆long long ,一种方法是用除法,但是效率比较低所以用了int128)
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 100010
#define mid (l+r>>1)
#define LL __int128
#define M 1000000000000000000ll
using namespace std;
struct Edge{ int v,nt; LL c; } G[N<<1];
int h[N],sz[N],son[N],d[N],f[N],rk[N];
int top[N],b[N],n,m,cnt=0,clk=0; LL w[N<<2],val[N]; long long C,D;
LL mul(LL x,LL y){ return ~x&&~y?(x*y>=M?-1:x*y):-1; }
inline void adj(int x,int y,LL c){
G[++cnt]=(Edge){y,h[x],c}; h[x]=cnt;
}
void dfs(int x,int p){
f[x]=p; sz[x]=1; d[x]=d[p]+1;
for(int v,i=h[x];i;i=G[i].nt)
if((v=G[i].v)!=p){
dfs(v,x); val[v]=G[i].c;
sz[x]+=sz[v];
if(sz[v]>sz[son[x]]) son[x]=v;
}
}
void dijk(int x,int p){
b[x]=++clk; rk[clk]=x; top[x]=p;
if(son[x]) dijk(son[x],p);
for(int v,i=h[x];i;i=G[i].nt)
if((v=G[i].v)!=f[x] && v!=son[x]) dijk(v,v);
}
void build(int l,int r,int x){
if(l==r){ w[x]=val[rk[l]]; return; }
build(l,mid,x<<1);
build(mid+1,r,x<<1|1);
w[x]=mul(w[x<<1],w[x<<1|1]);
}
void update(int l,int r,int x,int p,LL k){
if(l==r){ w[x]=k; return; }
if(p<=mid) update(l,mid,x<<1,p,k);
else update(mid+1,r,x<<1|1,p,k);
w[x]=mul(w[x<<1],w[x<<1|1]);
}
LL query(int l,int r,int x,int L,int R){
if(L<=l && r<=R) return w[x];
LL ans=1;
if(L<=mid) ans=mul(ans,query(l,mid,x<<1,L,R));
if(mid<R) ans=mul(ans,query(mid+1,r,x<<1|1,L,R));
return ans;
}
LL gLca(int x,int y){
LL A=1;
for(;top[x]!=top[y]&&~A;y=f[top[y]]){
if(d[top[x]]>d[top[y]]) swap(x,y);
A=mul(A,query(1,n,1,b[top[y]],b[y]));
}
if(d[x]>d[y]) swap(x,y);
A=mul(A,query(1,n,1,b[x]+1,b[y]));
return A;
}
int main(){
freopen("walk.in","r",stdin);
freopen("walk.out","w",stdout);
scanf("%d%d",&n,&m);
for(int x,y,i=1;i<n;++i){
scanf("%d%d%lld",&x,&y,&C);
adj(x,y,C); adj(y,x,C);
}
dfs(1,0); dijk(1,1); build(1,n,1);
for(int o,x,y;m--;){
scanf("%d",&o);
if(o==1){
scanf("%d%d%lld",&x,&y,&C);
D=gLca(x,y);
if(D==-1 || D>C) puts("0");
else printf("%lld\n",C/D);
} else {
scanf("%d%lld",&x,&C);
y=G[x<<1].v; x=G[(x<<1)-1].v;
if(f[y]==x) x=y;
update(1,n,1,b[x],C);
}
}
}