• HDU 5266 pog loves szh III


    题意:给出一棵树,1为根节点,求一段区间内所有点的最近公共祖先。

    解法:用一棵线段树维护区间LCA。LCA是dp做法。dp[i][j]表示点i的第2^j个祖先是谁,转移方程为dp[i][j] = dp[dp[i][j - 1]][j - 1],初始的dp[i][0]可以用一次dfs求得,这样可以用logn的时间求第x个祖先或查询LCA。求第x个祖先可以从二进制的角度理解,假设x是10,转化为二进制是1010,那么只要升2^3 + 2^1个深度就可以求出第x个祖先。求LCA的具体做法是,先将点a和b升至同一深度,如果此时a和b为同一个点,说明LCA就是a(或者b),如果不是同一个点,再同时向上升,直到已经无法找到两个点的祖先是不同点,说明两个点已经升至LCA的下一层,再向上升一层即为LCA。

    然后就是建一棵线段树,只需要查询,没有更新,查询的写法纠结了好久……

    因为代码写的太屎了,扩栈了依然会RE……所以只好用栈模拟……但是不扩栈又会T……不太理解那句扩栈用的语句的原理TUT……5000+ms擦边过了……

    代码:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<string.h>
    #include<math.h>
    #include<limits.h>
    #include<time.h>
    #include<stdlib.h>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #define LL long long
    #define lson l, m, rt << 1
    #define rson m + 1, r, rt << 1 | 1
    #pragma comment(linker, "/STACK:10240000000,10240000000")
    using namespace std;
    vector <int> tree[300005];
    bool vis[300005];
    int deep[300005];
    int dp[300005][30];
    int st[300005 << 2];
    struct node
    {
        int rt, dep;
        node(int rt, int dep) : rt(rt), dep(dep) {}
        node() {}
    };
    stack <node> s;
    int LCA(int a, int b)
    {
        if(deep[a] < deep[b])
            swap(a, b);
        for(int i = 20; i >= 0; i--)
        {
            if(deep[a] == deep[b])
                break;
            if(deep[dp[a][i]] >= deep[b])
                a = dp[a][i];
        }
        if(a == b)
            return a;
        for(int i = 20; i >= 0; i--)
        {
            if(dp[a][i] != dp[b][i])
            {
                a = dp[a][i];
                b = dp[b][i];
            }
        }
        return dp[a][0];
    }
    void pushUp(int rt)
    {
        st[rt] = LCA(st[rt << 1], st[rt << 1 | 1]);
    }
    void build(int l, int r, int rt)
    {
        if(l == r)
        {
            st[rt] = l;
            return ;
        }
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
        pushUp(rt);
    }
    int query(int ll, int rr, int l, int r, int rt)
    {
        if(ll <= l && rr >= r)
            return st[rt];
        int m = (l + r) >> 1;
        int res;
        if(ll <= m)
        {
            res = query(ll, rr, lson);
            if(rr > m)
                return LCA(res, query(ll, rr, rson));
            else
                return res;
        }
        else
            return query(ll, rr, rson);
    }
    int main()
    {
        int n;
        while(~scanf("%d", &n))
        {
            for(int i = 0; i < 300005; i++)
                tree[i].clear();
            for(int i = 0; i < n - 1; i++)
            {
                int a, b;
                scanf("%d%d", &a, &b);
                tree[a].push_back(b);
                tree[b].push_back(a);
            }
            memset(vis, 0, sizeof vis);
            memset(dp, 0, sizeof dp);
            vis[1] = true;
            dp[1][0] = 1;
            s.push(node(1, 1));
            while(!s.empty())
            {
                node top = s.top();
                deep[top.rt] = top.dep;
                int len = tree[top.rt].size();
                int flag = true;
                for(int i = 0; i < len; i++)
                {
                    if(!vis[tree[top.rt][i]])
                    {
                        vis[tree[top.rt][i]] = true;
                        dp[tree[top.rt][i]][0] = top.rt;
                        s.push(node(tree[top.rt][i], top.dep + 1));
                        flag = false;
                    }
                }
                if(flag)
                    s.pop();
            }
            for(int j = 1; j < 20; j++)
            {
                for(int i = 1; i <= n; i++)
                {
                    dp[i][j] = dp[dp[i][j - 1]][j - 1];
                }
            }
            build(1, n, 1);
            int q;
            scanf("%d", &q);
            for(int i = 0; i < q; i++)
            {
                int a, b;
                scanf("%d%d", &a, &b);
                printf("%d
    ", query(a, b, 1, n, 1));
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    c# 第41节 异常处理
    c# 第40节 密封类、密封方法
    c# 第39节 抽象类、抽象方法
    c# 第38节 接口的实现
    c# 第37节 接口的实现与继承
    c# 第36节 接口的声明
    测试面试题集-接口测试
    Python接口自动化测试系列文章汇总
    Jmeter系列之简介与环境安装
    Python接口自动化之logging封装及实战
  • 原文地址:https://www.cnblogs.com/Apro/p/4563247.html
Copyright © 2020-2023  润新知