题目链接

题意:

  有n个点的一棵树,两种操作:

  1. a到b的路径上,给一个y,对于路径上每一条边,进行操作,问最后的y;

  2. 修改某个条边p的值为c

思路:

  链上操作的问题,想树链剖分和LCT,对于第一种操作,因为是向下取整,考虑y除以路径上所有边乘积,即;对于第二种操作,就是线段树上的单点更新。因为给的是边的序号,首先每个id能知道对应的边值(ide[])和连接的点(idv[])。还有乘法溢出的处理,写成函数方便多了。

另外:

  1. 用dfn来替换dep完全没有问题,那以后就用dfn吧。2. 第二次DFS,要先去重儿子的路,这样dfn[son[u]]=dfn[u]+1,son数组也省了。3. 代码debug水平有待提升。4. 树的建图用vector就行了,不需要邻接表(n-1条边)。

#include <bits/stdc++.h>

typedef long long ll;
const int N = 2e5 + 5;
const ll INF = 2e18;

std::vector<std::pair<int, int> > edges[N];
int n, m;

int dfn[N], fa[N], son[N], sz[N], belong[N];
ll ide[N];
int idv[N];
int tim;

inline ll mul(ll a, ll b) {
    if (a != 0 && b > INF / a) return INF;
    return a * b;
}

void DFS2(int u, int chain) {
    dfn[u] = ++tim;
    belong[u] = chain;
    if (son[u] != 0) {
        DFS2 (son[u], chain);
    }
    for (auto e: edges[u]) {
        int v = e.first;
        if (v == fa[u] || v == son[u]) continue;
        DFS2 (v, v);
    }
}

void DFS1(int u, int pa) {
    sz[u] = 1;
    fa[u] = pa;
    for (auto e: edges[u]) {
        int v = e.first, id = e.second;
        if (v == pa) continue;
        idv[id] = v;
        DFS1 (v, u);
        if (sz[v] > sz[son[u]]) son[u] = v;
        sz[u] += sz[v];
    }
}

#define lson l, mid, o << 1
#define rson mid + 1, r, o << 1 | 1

ll val[N<<2];

void push_up(int o) {
    val[o] = mul (val[o<<1], val[o<<1|1]);
}

void tree_updata(int p, ll c, int l, int r, int o) {
    if (l == r) {
        val[o] = c;
        return ;
    }
    int mid = l + r >> 1;
    if (p <= mid) tree_updata (p, c, lson);
    else tree_updata (p, c, rson);
    push_up (o);
}

ll tree_query(int ql, int qr, int l, int r, int o) {
    if (ql <= l && r <= qr) {
        return val[o];
    }
    int mid = l + r >> 1;
    ll ret = 1;
    if (ql <= mid) ret = mul (ret, tree_query (ql, qr, lson));
    if (qr > mid) ret = mul (ret, tree_query (ql, qr, rson));
    return ret;
}

ll query(int a, int b) {
    ll ret = 1;
    int p = belong[a], q = belong[b];
    while (p != q) {
        if (dfn[p] < dfn[q]) {
            std::swap (p, q);
            std::swap (a, b);
        }
        ret = mul (ret, tree_query (dfn[p], dfn[a], 1, n, 1));
        a = fa[p];
        p = belong[a];
    }
    if (dfn[a] < dfn[b]) std::swap (a, b);
    if (a != b) {
        ret = mul (ret, tree_query (dfn[son[b]], dfn[a], 1, n, 1));
    }
    return ret;
}

void modify(int id, ll c) {
    tree_updata (dfn[idv[id]], c, 1, n, 1);
}

void prepare() {
    DFS1 (1, 0);
    tim = 0;
    DFS2 (1, 1);
    for (int i=1; i<n; ++i) {
        tree_updata (dfn[idv[i]], ide[i], 1, n, 1);
    }
}

int main() {
    scanf ("%d%d", &n, &m);
    for (int i=1; i<n; ++i) {
        int u, v;
        ll w;
        scanf ("%d%d%I64d", &u, &v, &w);
        ide[i] = w;
        edges[u].push_back ({v, i});
        edges[v].push_back ({u, i});
    }

    prepare ();

    for (int i=0; i<m; ++i) {
        int t, a, b;
        ll c;
        scanf ("%d%d", &t, &a);
        if (t == 1) {
            scanf ("%d%I64d", &b, &c);
            printf ("%I64d\n", c / query (a, b));
        } else {
            scanf ("%I64d", &c);
            modify (a, c);
        }
    }
    return 0;
}

  

树链剖分+线段树 CF 593D Happy Tree Party(快乐树聚会)的更多相关文章

  1. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  2. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  3. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  4. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  5. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  6. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  7. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  8. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

  9. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  10. bzoj2243[SDOI2011]染色 树链剖分+线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9012  Solved: 3375[Submit][Status ...

随机推荐

  1. 浅谈JavaScript之原型

    上一篇谈new关键字也是给这一篇写关于原型的文章买个伏笔,我对原型的理解可能会有偏差,如有错误,望指正一定修改,望各位道友如果想真正的理解原型的概念一定要再看完各方言论再回归教材. 言归正传谈原型,首 ...

  2. tomcat404报错解决

    本地启动tomcat,不报错.也可正常打开http://localhost:8080 但是eclipse中启动tomcat不报错.但是打开http://localhost:8080时报404 思考,原 ...

  3. 演示get、post请求如何算sn,算得sn如何使用

    import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.UnsupportedEncoding ...

  4. [翻译] java NIO Buffer

    原文地址:http://tutorials.jenkov.com/java-nio/buffers.html JAVA NIO 是在和channel交互的时候使用的.正如你所知道的,数据是从chann ...

  5. 树莓派 自身摄像头的opencv调用

    之前写过一篇随笔关于树莓派3上摄像头的调用,使用的方式是安装v4l2驱动. 实际上有一种更加简单的方法. 树莓派中的camera module是放在/boot/目录下以固件的形式加载的,不是一个标准的 ...

  6. java11-4 字符串的遍历以及字符串中各类字符的统计

    1.需求:获取字符串中的每一个字符   分析: A:如何能够拿到每一个字符呢?  char charAt(int index) B:我怎么知道字符到底有多少个呢? int length() publi ...

  7. 如何在Eclipse中查看Android源码或者第三方组件包源码

    文章出处:http://blog.csdn.net/cjjky/article/details/6535426 在学习过程中如果经常阅读源码,理解程度会比较深,学习效率也会比较高,那么如何方便快捷的阅 ...

  8. 如何实现GridView的选中,编辑,取消,删除功能

    protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e) { string sqlstr = &qu ...

  9. backup site collection

    http://stackoverflow.com/questions/5376380/sharepoint-2010-change-sitecollection-urlstsadm -o backup ...

  10. ANDROID_MARS学习笔记_S01原始版_008_Handler(异步消息处理机制)

    一.流程 1.点击按钮,则代码会使handler把updateThread压到队列里去,从而执行updateThread的run() 2.run()里会通过msg.arg1 = i 和bundle来写 ...