当前位置 博文首页 > 文章内容

    习题:Company(LCA)

    作者: 栏目:未分类 时间:2020-08-24 11:01:16

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



    题目

    传送门

    思路

    一个性质,一群节点的lca一定是其中dfn最小的的节点和dfn最大的节点的lca

    用线段树维护区间dfn的最大值和最小值即可

    代码

    #include<iostream>
    #include<vector>
    using namespace std;
    #define pii pair<int,int>
    #define x first
    #define y second
    namespace lst
    {
        struct node
        {
            int l,r;
            pii maxx;
            pii minn;
            //x表示值,y表示位置
        }tre[400005];
        void build(int l,int r,int k)
        {
            tre[k].l=l;
            tre[k].r=r;
            if(l==r)
                return;
            int mid=(l+r)>>1;
            build(l,mid,k<<1);
            build(mid+1,r,k<<1|1);
        }
        void change(int pos,int val,int k)
        {
            if(tre[k].l>pos||pos>tre[k].r)
                return;
            if(tre[k].l==tre[k].r)
            {
                tre[k].maxx.x=tre[k].minn.x=val;
                tre[k].maxx.y=tre[k].minn.y=tre[k].l;
                return;
            }
            change(pos,val,k<<1);
            change(pos,val,k<<1|1);
            tre[k].maxx=max(tre[k<<1].maxx,tre[k<<1|1].maxx);
            tre[k].minn=min(tre[k<<1].minn,tre[k<<1|1].minn);
        }
        pii ask_min(int l,int r,int k)
        {
            if(tre[k].l>r||l>tre[k].r)
                return make_pair(1<<30,0);
            if(l<=tre[k].l&&tre[k].r<=r)
                return tre[k].minn;
            return min(ask_min(l,r,k<<1),ask_min(l,r,k<<1|1));
        }
        pii ask_max(int l,int r,int k)
        {
            if(tre[k].l>r||l>tre[k].r)
                return make_pair(0,0);
            if(l<=tre[k].l&&tre[k].r<=r)
                return tre[k].maxx;
            return max(ask_max(l,r,k<<1),ask_max(l,r,k<<1|1));
        }
    }
    using namespace lst;
    int n,q,cnt;
    int dfn[100005];
    int dep[100005],dp[100005][25];
    vector<int> g[100005];
    void dfs(int u,int fa)
    {
        dfn[u]=++cnt;
        change(u,dfn[u],1);
        dep[u]=dep[fa]+1;
        for(int i=1;i<=20;i++)
            dp[u][i]=dp[dp[u][i-1]][i-1];
        for(int i=0;i<g[u].size();i++)
        {
            int v=g[u][i];
            if(v!=fa)
            {
                dp[v][0]=u;
                dfs(v,u);
            }
        }
    }
    int lca(int u,int v)
    {
        if(u==v)
            return u;
        if(dep[u]>dep[v])
            swap(u,v);
        for(int i=20;i>=0;i--)
            if(dep[u]<=dep[dp[v][i]])
                v=dp[v][i];
        if(u==v)
            return u;
        for(int i=20;i>=0;i--)
            if(dp[u][i]!=dp[v][i])
            {
                u=dp[u][i];
                v=dp[v][i];
            }
        return dp[u][0];
    }
    int solve(int l,int r,int cnt)
    {
        if(cnt==l)
        {
            pii t1=ask_max(l+1,r,1);
            pii t2=ask_min(l+1,r,1);
            return lca(t1.y,t2.y);
        }
        else if(cnt==r)
        {
            pii t1=ask_max(l,r-1,1);
            pii t2=ask_min(l,r-1,1);
            return lca(t1.y,t2.y);
        }
        else
        {
            pii t1=ask_max(l,cnt-1,1);
            pii t2=ask_min(l,cnt-1,1);
            pii s1=ask_max(cnt+1,r,1);
            pii s2=ask_min(cnt+1,r,1);
            return lca(lca(t1.y,t2.y),lca(s1.y,s2.y));
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin>>n>>q;
        build(1,n,1);
        for(int i=2,u;i<=n;i++)
        {
            cin>>u;
            g[i].push_back(u);
            g[u].push_back(i);
        }
        dep[0]=-1;
        dfs(1,0);
        for(int i=1,l,r;i<=q;i++)
        {
            cin>>l>>r;
            pii t1=ask_max(l,r,1),t2=ask_min(l,r,1);
            int lca1=solve(l,r,t1.y),lca2=solve(l,r,t2.y);
            if(dep[lca1]>dep[lca2])
                cout<<t1.y<<' '<<dep[lca1]<<'\n';
            else
                cout<<t2.y<<' '<<dep[lca2]<<'\n';
        }
        return 0;
    }