• 北方多校 又是一道简单题


    又是一道简单题

      •  12000ms
      •  65536K

    给出一棵有根树,每次查询给出两个节点 u 和 v,假设节点 f 是u,v的最近公共祖先,请查询以 f 为根的子树中,不在 u 到 v 这条链上且标号最小的节点。

    输入格式

    第一行输入正整数 T(T <= 30),表示共有T组输入数据。

    对于每组数据,第一行输入两个正整数 n,m(n <= 50000,m <= 50000),表示节点数和询问数,节点编号 1 到 n,其中 1 是根节点。

    接下来 n - 1 行,每行输入两个正整数u,v,表示标号为u和v的节点间有一条边。

    接下来 m 行,每行输入两个正整数u,v,表示一次询问。

    保证所有输入数据均合法。

    输出格式

    对于每次询问,输出答案。如不存在输出-1。

    样例输入

    1
    3 3
    1 2
    1 3
    1 2
    1 3
    2 3

    样例输出

    3
    2
    -1
    分析:考虑树链剖分;
       把子树按dfs序可以展开到一维,然后对于链,可以将这个区间分成logn的部分,对于每个部分求最小值即可;
       复杂度nlognlogn;
    代码:
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <climits>
    #include <cstring>
    #include <string>
    #include <set>
    #include <bitset>
    #include <map>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cassert>
    #include <ctime>
    #define rep(i,m,n) for(i=m;i<=n;i++)
    #define mod 1000000007
    #define inf 0x3f3f3f3f
    #define vi vector<int>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define pi acos(-1.0)
    #define pii pair<int,int>
    #define ls rt<<1
    #define rs rt<<1|1
    #define sys system("pause")
    const int maxn=1e5+10;
    const int N=1e5+10;
    using namespace std;
    ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
    ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p%mod;p=p*p%mod;q>>=1;}return f;}
    int n,m,k,t,st[maxn],ed[maxn],dep[maxn],fa[20][maxn],bel[maxn],son[maxn],pos[maxn],a[maxn],dfs_cl,mi[maxn<<2];
    vi e[maxn];
    void dfs1(int x,int y)
    {
        dep[x]=dep[y]+1;
        fa[0][x]=y;
        son[x]=1;
        for(int i=1;fa[i-1][fa[i-1][x]];i++)
        {
            fa[i][x]=fa[i-1][fa[i-1][x]];
        }
        for(int i=0;i<e[x].size();i++)
        {
            int z=e[x][i];
            if(z==y)continue;
            dfs1(z,x);
            son[x]+=son[z];
        }
    }
    void dfs2(int x,int y,int ch)
    {
        int ma=0;
        pos[x]=++dfs_cl;
        st[x]=dfs_cl;
        a[dfs_cl]=x;
        bel[x]=ch;
        for(int i=0;i<e[x].size();i++)
        {
            int z=e[x][i];
            if(z==y)continue;
            if(son[z]>son[ma])ma=z;
        }
        if(ma!=0)dfs2(ma,x,ch);
        for(int i=0;i<e[x].size();i++)
        {
            int z=e[x][i];
            if(z==y||z==ma)continue;
            dfs2(z,x,z);
        }
        ed[x]=dfs_cl;
    }
    int lca(int x,int y)
    {
        if(dep[x]<dep[y])swap(x,y);
        for(int i=19;i>=0;i--)if(dep[fa[i][x]]>=dep[y])x=fa[i][x];
        if(x==y)return x;
        for(int i=19;i>=0;i--)
        {
            if(fa[i][x]!=fa[i][y])x=fa[i][x],y=fa[i][y];
        }
        return fa[0][x];
    }
    void pup(int l,int r,int rt)
    {
        mi[rt]=min(mi[ls],mi[rs]);
    }
    void build(int l,int r,int rt)
    {
        if(l==r)
        {
            mi[rt]=a[l];
            return;
        }
        int mid=l+r>>1;
        build(l,mid,ls);
        build(mid+1,r,rs);
        pup(l,r,rt);
    }
    int gao(int L,int R,int l,int r,int rt)
    {
        if(L==l&&R==r)return mi[rt];
        int mid=l+r>>1;
        if(R<=mid)return gao(L,R,l,mid,ls);
        else if(L>mid)return gao(L,R,mid+1,r,rs);
        else return min(gao(L,mid,l,mid,ls),gao(mid+1,R,mid+1,r,rs));
    }
    void upd(vector<int>&a,int x,int y)
    {
        while(bel[x]!=bel[y])
        {
            if(dep[bel[x]]<dep[bel[y]])swap(x,y);
            a.pb(pos[x]);
            a.pb(pos[bel[x]]);
            x=fa[0][bel[x]];
        }
        if(pos[x]>pos[y])swap(x,y);
        a.pb(pos[y]);
        a.pb(pos[x]);
    }
    int main()
    {
        int i,j;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
            rep(i,1,n)e[i].clear();
            rep(i,1,n)rep(j,0,19)fa[j][i]=0;
            rep(i,1,n-1)scanf("%d%d",&j,&k),e[j].pb(k),e[k].pb(j);
            dfs1(1,0);
            dfs_cl=0;
            dfs2(1,0,1);
            build(1,n,1);
            while(m--)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                vector<int>tmp;
                int lc=lca(x,y);
                upd(tmp,x,y);
                int s=st[lc],t=ed[lc];
                if(lc<1||lc>n)return 0;
                sort(tmp.begin(),tmp.end());
                int mi=1e9;
                for(i=0;i<tmp.size();i+=2)
                {
                    if(s<=tmp[i]-1)mi=min(mi,gao(s,tmp[i]-1,1,n,1));
                    s=tmp[i+1]+1;
                }
                if(s<=t)mi=min(mi,gao(s,t,1,n,1));
                printf("%d
    ",mi==1e9?-1:mi);
            }
        }
        return 0;
    }
  • 相关阅读:
    CSS hack
    百度前端技术学院-task1.8源代码
    不用bootstrap,只用CSS创建网格布局
    【转】CSS3的calc()使用——精缩版
    百度前端技术学院task16源代码
    【转】正则表达式 匹配中文,英文字母和数字及_的写法!同时控制长度
    【转】潜说js对象和数组
    百度前端技术学院-task1.3源代码
    百度前端技术学院task15源代码
    百度前端技术学院task14源代码
  • 原文地址:https://www.cnblogs.com/dyzll/p/6973627.html
Copyright © 2020-2023  润新知