题目链接
新地址链接
给出一棵树,每棵树有value值,两种操作:1 u v x, 用x依次除以u到v路径上的数,然后
输出x,2 p x, 把第p条边的权值改为x. 直接树链剖分,然后用线段树维护乘积即可。注意
乘积可能爆long long , 可以用inf/a如果
#include
#include
#include
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
using namespace std;
typedef long long Long;
const int maxn = 2e5 + 10;
const int maxe = maxn*2;
const Long inf = 1e18 + 10000;
struct divTree
{
void add_edge(int u, int v, Long c)
{
edges[cnt_edge] = Edge(u, v, c, fir[u]);
fir[u] = cnt_edge++;
}
void init()
{
memset(fir, -1, sizeof(fir));
cnt_edge = 0;
}
void dfs1(int u)
{
sz[u] = 1; son[u] = 0;
for (int e = fir[u]; e != -1; e = edges[e].x)
{
int v = edges[e].v; if (v == fa[u]) continue;
dep[v] = dep[u]+1; fa[v] = u;
dfs1(v);
sz[u] += sz[v];
if (sz[son[u]] < sz[v])
{
son[u] = v;
}
}
}
void dfs2(int u)
{
if (son[u])
{
faEdge[son[u]] = ++no;
train[son[u]] = train[u];
dfs2(son[u]);
}
for (int e = fir[u]; e != -1; e = edges[e].x)
{
int v = edges[e].v; if (v == fa[u]) continue;
if (v == son[u])
{
val[faEdge[v]] = edges[e].c;
mp[e/2+1] = faEdge[v];
}
else
{
faEdge[v] = ++no;
val[no] = edges[e].c; mp[e/2+1] = no;
train[v] = v;
dfs2(v);
}
}
}
void pushUp(int o)
{
if (inf / sum[o<<1] < sum[o<<1|1]) sum[o] = inf;
else sum[o] = sum[o<<1]*sum[o<<1|1];
}
void build(int o, int l, int r)
{
if (l == r)
{
sum[o] = val[l];
return ;
}
int m = (l + r) >> 1;
build(lson); build(rson);
pushUp(o);
}
void run(int rt)
{
dep[rt] = 1; fa[rt] = rt;
dfs1(rt);
no = 0; train[rt] = rt;
dfs2(rt);
build(1, 1, no);
}
void update(int p, Long v, int o, int l, int r)
{
if (l == r)
{
sum[o] = v;
return ;
}
int m = (l + r) >> 1;
if (p <= m) update(p, v, lson);
else update(p, v, rson);
pushUp(o);
}
Long query(int a, int b, int o, int l, int r)
{
if (a <= l && b >= r)
{
return sum[o];
}
int m = (l + r) >> 1;
if (a <= m && b > m)
{
Long v1 = query(a, b, lson), v2 = query(a, b, rson);
if (inf/v1 < v2) return inf;
else return v1*v2;
}
else if (a <= m) return query(a, b, lson);
else return query(a, b, rson);
}
Long gao(int u, int v)
{
Long ret = 1;
for (int fu=train[u], fv=train[v]; fu != fv; fu=train[u],fv=train[v])
{
if (dep[fu] < dep[fv])
{
swap(u, v); swap(fu, fv);
}
Long now = query(faEdge[fu], faEdge[u], 1, 1, no);
if (inf/now < ret) ret = inf;
else ret = ret * now;
u = fa[fu];
}
if (u == v) return ret;
if (dep[u] > dep[v]) swap(u, v);
Long now = query(faEdge[son[u]], faEdge[v], 1, 1, no);
if (inf/now < ret) ret = inf;
else ret = ret * now;
return ret;
}
struct Edge
{
int u, v, x;
Long c;
Edge(int u = 0, int v = 0, Long c = 0, int x = 0) : u(u), v(v), c(c), x(x) {}
} edges[maxe];
int fir[maxn], cnt_edge, no;
int dep[maxn], sz[maxn], fa[maxn], son[maxn];
int train[maxn], mp[maxn], faEdge[maxn];
Long val[maxn], sum[maxn<<2];
} divt;
int main()
{
int n, m; scanf("%d%d", &n, &m);
divt.init();
for (int i = 0; i < n-1; i++)
{
int u, v; Long c; scanf("%d%d%I64d", &u, &v, &c);
divt.add_edge(u, v, c);
divt.add_edge(v, u, c);
}
divt.run(1);
for (int i = 0; i < m; i++)
{
int cmd; scanf("%d", &cmd);
if (cmd == 1)
{
int a, b; Long v; scanf("%d%d%I64d", &a, &b, &v);
Long now = divt.gao(a, b);
printf("%I64d\n", v/now);
}
else
{
int p; Long v; scanf("%d%I64d", &p, &v);
divt.update(divt.mp[p], v, 1, 1, divt.no);
}
}
return 0;
}