• 树链剖分


    入门看这篇http://blog.sina.com.cn/s/blog_7a1746820100wp67.html

    一个入门题目

    QTREE - Query on a tree

    no tags 

    You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1.

    We will ask you to perfrom some instructions of the following form:

    • CHANGE i ti : change the cost of the i-th edge to ti
      or
    • QUERY a b : ask for the maximum edge cost on the path from node a to node b

    Input

    The first line of input contains an integer t, the number of test cases (t <= 20). t test cases follow.

    For each test case:

    • In the first line there is an integer N (N <= 10000),
    • In the next N-1 lines, the i-th line describes the i-th edge: a line with three integers a b c denotes an edge between a, b of cost c (c <= 1000000),
    • The next lines contain instructions "CHANGE i ti" or "QUERY a b",
    • The end of each test case is signified by the string "DONE".

    There is one blank line between successive tests.

    Output

    For each "QUERY" operation, write one integer representing its result.

    Example

    Input:
    1
    
    3
    1 2 1
    2 3 2
    QUERY 1 2
    CHANGE 1 3
    QUERY 1 2
    DONE
    
    Output:
    1
    3
    
    
    代码:
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1 
    using namespace std;
    
    const int maxn = 10010;
    struct Node{
        int to, next;
    };
    int p[maxn];//先线段树中的位置,dfs序 
    int tree[maxn*4]; //线段树 
    int fa[maxn];//保存当前节点的父亲节点 
    int top[maxn];//表示当前节点所在链顶端的节点 
    int siz[maxn];//当前节点的所有子节点数目 
    int deep[maxn];//当前节点的深度 
    int head[maxn];//前向星表示 
    int son[maxn];//当前节点的重儿子 
    Node edge[maxn*2];//前向星的表示法 
    int e[maxn][3];//边集 
    int tot, pos;//tot表示前向星中的所有节点个数,pos表示在线段树中的位置 
    
    int Max(int a, int b)
    {
        return a > b ? a : b;
    }
    
    void init()
    {
        tot = 0;//初始化为0 
        pos = 1;//因为我写的线段树1是根节点,所以这个从1开始 
        memset(head, -1, sizeof(head));
        memset(son, -1, sizeof(son));    
    }
    //添加边 
    void addedge(int u, int v)
    {
        edge[tot].to = v; 
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    //第一个dfs,求出来当前节点有多少个孩子,它的父亲,深度,还有重儿子 
    void dfs1(int u, int pre, int d)
    {
        siz[u] = 1;
        fa[u] = pre;
        deep[u] = d;
        
        for (int i = head[u]; i != -1; i = edge[i].next)//遍历所有的边 
        {
            int v = edge[i].to;
            if (v != pre)//不能向上走,因为这是无向图 
            {
                dfs1(v, u, d + 1);
                siz[u] += siz[v];
                if (son[u] == -1 || siz[son[u]] < siz[v])
                    son[u] = v;        
            }
        }
    }
    //第二个dfs求出来top,和p 
    void dfs2(int u, int sp)
    {
        top[u] = sp;
        if (son[u] != -1)//不是叶子顶点 
        {
            p[u] = pos++;
            dfs2(son[u], sp);
        }
        else//叶子顶点 
        {
            p[u] = pos++;
            return;
        }
        for (int i = head[u]; i != -1; i = edge[i].next)//找它的连接的所有顶点 
        {
            int v = edge[i].to;
            if (son[u] != v && v != fa[u])//不是重儿子并且不能向上找 
            {
                dfs2(v, v);
            }
        } 
    }
    //线段树 
    void pushup(int rt)
    {
        tree[rt] = Max(tree[rt<<1], tree[rt<<1|1]);
    }
    
    void build(int l, int r, int rt)
    {
        if (l == r)
        {
            tree[rt] = 0;
            return;
        }
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
        pushup(rt); 
    }
    void update(int p, int sc, int l, int r, int rt)
    {
        if (l == r)
        {
            tree[rt] = sc;
            return;
        }
        int m = (l + r) >> 1;
        if (p <= m)
            update(p, sc, lson);
        else
            update(p, sc, rson);
        pushup(rt); 
    }
    
    int query(int L, int R, int l, int r, int rt)
    {
        if (L <= l && r <= R)
        {
            return tree[rt];
        }
        int m = (l + r) >> 1;
        int res = 0;
        if (L <= m)
            res = Max(res, query(L, R, lson));
        if (R > m)
            res = Max(res, query(L, R, rson));
        return res;
    }
    //查询u->v边的最大值 
    int find(int u, int v)
    {
        int f1 = top[u], f2 = top[v];
        int ans = 0;
        while (f1 != f2)
        {
            if (deep[f1] < deep[f2])
            {
                swap(f1, f2);
                swap(u, v);
            }
            ans = Max(ans, query(p[f1], p[u], 1, pos - 1, 1));
            u = fa[f1];
            f1 = top[u];
        }
        if (u == v)
            return ans;
        if (deep[u] > deep[v])
            swap(u, v);
        return Max(ans, query(p[son[u]], p[v], 1, pos - 1, 1));    
    }
    
    int main()
    {
        //freopen("in.txt", "r", stdin);
        int T, n;
        scanf("%d", &T);
        while (T--)
        {
            init();
            scanf("%d", &n);
            for (int i = 0; i < n - 1; i++)
            {
                scanf("%d %d %d", &e[i][0], &e[i][1], &e[i][2]);
                addedge(e[i][0], e[i][1]);//无向图,所以添加两次 
                addedge(e[i][1], e[i][0]);
            }
            dfs1(1, 0, 0);
            dfs2(1, 1);
            build(1, pos - 1, 1);
            for (int i = 0; i < n - 1; i++)
            {
                if (deep[e[i][0]] > deep[e[i][1]])
                    swap(e[i][0], e[i][1]);
                update(p[e[i][1]], e[i][2], 1, pos - 1, 1);//将权值更新到线段树中 
            }
            
            char op[10];
            int u, v;
            while (~scanf("%s", op))
            {
                if (op[0] == 'D')
                    break;
                else if (op[0] == 'C')
                {
                    scanf("%d %d", &u, &v);
                    update(p[e[u - 1][1]], v, 1, pos - 1, 1);
                }
                else
                {
                    scanf("%d %d", &u, &v);
                    int t = find(u, v);
                    printf("%d
    ", t);
                }
            }
        }    
        
        return 0;
    }
  • 相关阅读:
    使用Fiddle修改请求数据
    Fiddle抓包应用概述
    s = -1 #作用域之外的数字是不会改的
    python list.reverse() 方法 不可以 ss = li.reverse() ,这个列表翻转方法没有返回值, ss=None
    python 两个tuple元组之间连接判断是否有一个为空, and 和 & ,只能用and 不能用&
    http 协议最大url是不限制的,但实际上不会很长,有服务器的限制
    这个居然也可以python >>>geturl()["a"]
    python的字典可以这样子 print(dic["ab"+cd]) 震惊!!!
    mysql 远程 死活连不上 阿里云搞得个什么鬼
    txt默认的是个什么格式,anex,什么的,另存为utf-8或者unicode中文就不乱了
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/4557231.html
Copyright © 2020-2023  润新知