zoukankan      html  css  js  c++  java
  • SPOJ

    题目链接


    题意:给一棵树,树的边上是有权值的。
    输入给n-1条边,有两种操作:

    • CHANGE i j 将第i条边的权值改为j
    • QUERY i j 询问节点i到节点j路径上的权值最大值

    思路:

    • 树链剖分处理出每条链,放到数组中,使用线段树来维护。
    • 因为是边上的权值,所以将其转为点上的权值,转变为深度较大的点上的权值。
    • 使用线段树是因为它支持动态查询区间最值和单点修改。

    写错了的几次是因为对于使用点上的权值,所以处理同一条链上的最大值的时候,例如 u -> v 的链时,要查询的时u+1 -> v的最大值。

    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    #include <stdlib.h>
    #include <vector>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <stack>
    #include <string>
    #include <math.h>
    #include <bitset>
    #include <ctype.h>
    #define CLR(n,b) memset(n, b, sizeof(n))
    using namespace std;
    typedef pair<int,int> P;
    typedef long long LL;
    const int INF = 0x3f3f3f3f;
    const double PI = acos(-1.0);
    const double eps = 1e-9;
    const int N = 2e4 + 5;
    const int mod = 1e9 + 7;
    struct Edge
    {
        int u,v,w;
        Edge() {}
        Edge(int a, int b, int c): u(a), v(b), w(c) {}
    };
    int fa[N],son[N], p[N],fp[N], top[N],dep[N],sz[N];
    int a[N];
    int pos;
    int n,m,k;
    vector<Edge> edges;
    vector<int> G[N];
    void init(int n)
    {
        CLR(fa, 0);  CLR(son, -1); CLR(p, -1); CLR(a, 0);
        CLR(fp, -1); CLR(top, 0); CLR(sz, 0); CLR(dep, 0);
        pos = 0; edges.clear();
        for(int i = 0; i <= n; i++) G[i].clear();
    }
    void addedge(int u, int v, int w)
    {
        edges.push_back(Edge(u,v,w));
        edges.push_back(Edge(v,u,w));
        int m = edges.size();
        G[u].push_back(m-2);
        G[v].push_back(m-1);
    }
    
    
    void dfs(int u, int pre, int d)
    {
        fa[u] = pre;
        dep[u] = d;
        sz[u] = 1;
        son[u] = -1;
        for(int i = 0; i < G[u].size(); i++)
        {
            Edge &e = edges[G[u][i]];
            int v = e.v;
            if(v == pre) continue;
            dfs(v, u, d+1);
            a[v] = e.w;
            sz[u] += sz[v];
            if(son[u] == -1 || sz[son[u]] < sz[v])
                son[u] = v;
        }
    }
    
    void getpos(int u, int sp)
    {
        top[u] = sp;
        p[u] = ++pos;
        fp[p[u]] = u;
        if(son[u] == -1) return;
        getpos(son[u], sp);
        for(int i = 0; i < G[u].size(); i++)
        {
            Edge &e = edges[G[u][i]];
            int v = e.v;
            if(v == son[u] || v == fa[u]) continue;
            getpos(v, v);
        }
    }
    
    
    int Max[N<<2];
    void build(int rt, int l, int r)
    {
        if(l == r)
        {
            Max[rt] = -INF;
            return;
        }
        int mid = l+r >> 1;
        build(rt << 1, l, mid);
        build(rt << 1 |1, mid+1, r);
        Max[rt] = max(Max[rt<<1], Max[rt<<1|1]);
    }
    void update(int pos, int val, int rt, int l, int r)
    {
        if(pos < l || pos > r) return;
        int mid = l+r >> 1;
        if(l == r)
        {
            Max[rt] = val;
            return;
        }
        if(pos > mid) update(pos, val, rt << 1 | 1, mid+1, r);
        else update(pos, val, rt << 1, l, mid);
        Max[rt] = max(Max[rt<<1], Max[rt<<1|1]);
    }
    int query(int L, int R, int rt, int l, int r)
    {
        if(L <= l && r <= R) return Max[rt];
        int mid = l+r >> 1;
        int ans = 0;
        if(mid >= L) ans = max(ans, query(L, R, rt<<1, l, mid));
        if(mid < R) ans = max(ans, query(L, R, rt<<1|1, mid+1, r));
        return ans;
    }
    
    
    
    int Query(int u, int v)
    {
        int f1 = top[u], f2 = top[v];
        int ans = 0;
        while(f1 != f2)
        {
            if(dep[f1] < dep[f2])
            {
                swap(f1, f2);
                swap(u, v);
            }
    
            ans = max(ans, query(p[f1], p[u], 1, 1, n));
            u = fa[f1];
            f1 = top[u];
        }
        if(u == v) return ans;
        if(dep[u] > dep[v]) swap(u, v);
        /**WA**/
        ans = max(ans, query(p[u]+1, p[v], 1, 1, n));
        /****/
        return ans;
    }
    int t;
    int main()
    {
        scanf("%d", &t);
        while(t--)
        {
            scanf("%d", &n);
            init(n);
            for(int i = 0; i < n-1; i++)
            {
                int u,v,w;
                scanf("%d%d%d", &u, &v, &w);
                addedge(u,v,w);
            }
            dfs(1,1,0);
            getpos(1,1);
            build(1,1,n);
            for(int i = 1; i <= n; i++)
                update(p[i], a[i], 1, 1, n);
            while(true)
            {
                char cmd[10];
                int x,y;
                scanf("%s", cmd);
                if(cmd[0] == 'D') break;
                scanf("%d%d", &x,&y);
                if(cmd[0] == 'Q')
                    printf("%d
    ", Query(x,y));
                else
                {
                    int u = edges[x*2-2].u, v = edges[x*2-2].v;
                    if(dep[u] < dep[v]) swap(u,v);
                    update(p[u], y, 1, 1, n);
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    bit、byte、word的区别
    JavaScript
    品牌的意义
    Java开发
    Java:关于implements Serializable的警告问题
    文件路径:/和的区别
    Iterator
    parameter和argument的区别
    Java中private、protected、public和default的区别
    Java异常
  • 原文地址:https://www.cnblogs.com/Alruddy/p/7492403.html
Copyright © 2011-2022 走看看