codeforces 593D 树链剖分

题目链接
新地址链接
给出一棵树,每棵树有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;
}

你可能感兴趣的:(ACM)