CF593D. Happy Tree Party(树剖模板)
https://codeforces.com/problemset/problem/593/D
看到题目是逐步向下取整我还想了一下……其实对于整型来说和把路径上的值乘在一起统一除效果是一样的。
这题还有一个点就是它的权值是依附于边而非点,对此我们可以把每个点和它连向fa的边绑定,把这个权值重新转换到点上,因为每个点只有一个fa。而对于根我们可以给它一个向上的虚边赋值1,这个过程用一个简单dfs来做
实际写题当中wa了好久……最后才发现是线段树的update参数没用ll
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=2e5+2;
const ll inf=1e18;
#define lson (o<<1)
#define rson (o<<1|1)
int n,m;
struct edge{
int to,next;
ll x;
}es[maxn<<1];
int cnt,head[maxn];
void add(int u,int v,ll x){
es[++cnt]={v,head[u],x};
head[u]=cnt;
}
ll mul(ll a,ll b){
if(inf/a<b)
return inf+5;
return a*b;
}
int fa[maxn],dep[maxn],son[maxn],siz[maxn];
void dfs1(int o,int from,int d){
fa[o]=from;
dep[o]=d;
siz[o]=1;
int tmp=0;
for(int i=head[o];i;i=es[i].next){
int v=es[i].to;
if(v==from)
continue;
dfs1(v,o,d+1);
if(siz[v]>tmp){
tmp=siz[v];
son[o]=v;
}
siz[o]+=siz[v];
}
}
int dfn[maxn],top[maxn],rnk[maxn],tot;
void dfs2(int o,int t){
dfn[o]=++tot;
rnk[dfn[o]]=o;
top[o]=t;
if(son[o]){
dfs2(son[o],t);
}
for(int i=head[o];i;i=es[i].next){
int v=es[i].to;
if(dfn[v]||v==son[o])
continue;
dfs2(v,v);
}
}
ll val[maxn<<2];
ll xp[maxn];
void build(int o,int l,int r){
//节点o管辖[l,r]区间
//val[o]=1;
if(l==r){
val[o]=xp[rnk[l]];
return ;
}
int mid=(l+r)/2;
build(lson,l,mid);
build(rson,mid+1,r);
//val[o]=(val[lson]>inf/val[rson]?inf+5:val[lson]*val[rson]);
val[o]=mul(val[lson],val[rson]);
}
void update(int o,int l,int r,int pos,ll c){
//将pos位置的xp替换为c
if(l==r){
val[o]=c;
return ;
}
int mid=(l+r)/2;
if(pos<=mid){
update(lson,l,mid,pos,c);
}else{
update(rson,mid+1,r,pos,c);
}
//val[o]=(val[lson]>inf/val[rson]?inf+5:val[lson]*val[rson]);
val[o]=mul(val[lson],val[rson]);
}
ll query(int o,int l,int r,int L,int R){
if(l>=L&&r<=R){
return val[o];
}
int mid=(l+r)/2;
ll res=1;
if(L<=mid){
res=mul(res,query(lson,l,mid,L,R));
}
if(R>mid){
ll tmp=query(rson,mid+1,r,L,R);
//res=(res>1e18/tmp?inf+5:res*tmp);
res=mul(res,tmp);
}
return res;
}
void dfs3(int o){
//用来把边权转化为儿子的点权
for(int i=head[o];i;i=es[i].next){
int v=es[i].to;
if(fa[v]==o){
xp[v]=es[i].x;
dfs3(v);
}
}
}
ll solve(int a,int b){
ll res=1,tmp;
int ta=top[a],tb=top[b];
while(ta!=tb){
if(dep[ta]<dep[tb]){
swap(ta,tb);
swap(a,b);
}
tmp=query(1,1,n,dfn[ta],dfn[a]);
//res=(res>1e18/tmp?inf+5:res*tmp);
res=mul(res,tmp);
a=fa[ta];
ta=top[a];
}
if(a!=b){
if(dep[a]<dep[b])
swap(a,b);
tmp=query(1,1,n,dfn[son[b]],dfn[a]);
//res=(res>1e18/tmp?inf+5:res*tmp);
res=mul(res,tmp);
}
return res;
}
int main(){
cin>>n>>m;
for(int i=1,u,v;i<n;i++){
ll x;
cin>>u>>v>>x;
add(u,v,x);
add(v,u,x);
}
dfs1(1,0,1);
dfs2(1,1);
dfs3(1);
xp[rnk[1]]=1;
build(1,1,n);
for(int i=1,opt;i<=m;i++){
cin>>opt;
if(opt==1){
int a,b;
ll y,x;
cin>>a>>b>>y;
x=solve(a,b);
cout<<y/x<<endl;
}else{
int pos;
ll c;
cin>>pos>>c;
int u=es[pos*2-1].to,v=es[pos*2].to;
if(fa[v]!=u)
swap(u,v);
update(1,1,n,dfn[v],c);
}
}
}
/*
4 3
1 2 1
2 4 3
2 3 2
2 3 4
1 3 4 6
*/