• 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)


    链接:https://ac.nowcoder.com/acm/contest/881/A
    来源:牛客网

    Equivalent Prefixes
    时间限制:C/C++ 2秒,其他语言4秒
    空间限制:C/C++ 524288K,其他语言1048576K
    64bit IO Format: %lld
    题目描述
    Two arrays u and v each with m distinct elements are called equivalent if and only if
    R
    M
    Q
    (
    u
    ,
    l
    ,
    r
    )

    R
    M
    Q
    (
    v
    ,
    l
    ,
    r
    )
    RMQ(u,l,r)=RMQ(v,l,r) for all
    1

    l

    r

    m
    1≤l≤r≤m
    where
    R
    M
    Q
    (
    w
    ,
    l
    ,
    r
    )
    RMQ(w,l,r) denotes the index of the minimum element among
    w
    l
    ,
    w
    l
    +
    1
    ,

    ,
    w
    r
    wl,wl+1,…,wr.
    Since the array contains distinct elements, the definition of minimum is unambiguous.

    Bobo has two arrays a and b each with n distinct elements. Find the maximum number
    p

    n
    p≤n where
    {
    a
    1
    ,
    a
    2
    ,

    ,
    a
    p
    }
    {a1,a2,…,ap} and
    {
    b
    1
    ,
    b
    2
    ,

    ,
    b
    p
    }
    {b1,b2,…,bp} are equivalent.
    输入描述:
    The input consists of several test cases and is terminated by end-of-file.

    The first line of each test case contains an integer n.
    The second line contains n integers
    a
    1
    ,
    a
    2
    ,

    ,
    a
    n
    a1,a2,…,an.
    The third line contains n integers
    b
    1
    ,
    b
    2
    ,

    ,
    b
    n
    b1,b2,…,bn.

    1

    n

    10
    5
    1≤n≤105
    *
    1

    a
    i
    ,
    b
    i

    n
    1≤ai,bi≤n
    *
    {
    a
    1
    ,
    a
    2
    ,

    ,
    a
    n
    }
    {a1,a2,…,an} are distinct.
    *
    {
    b
    1
    ,
    b
    2
    ,

    ,
    b
    n
    }
    {b1,b2,…,bn} are distinct.

    • The sum of n does not exceed
      5
      ×
      10
      5
      5×105.
      输出描述:
      For each test case, print an integer which denotes the result.
      示例1
      输入
      复制
      2
      1 2
      2 1
      3
      2 1 3
      3 1 2
      5
      3 1 5 2 4
      5 2 4 3 1
      输出
      复制
      1
      3
      4

    题意:
    给你两个数组a,b,大小为n,让你寻找一个数p (1<= p <= n) ,使之在 1~p 任意一个区间中a,b数组的最小值下标相同。
    思路:

    容易知道p的取值具有单调性,首先我们用st表在对数组a,b进行预处理,方便后续的RMQ,因为数组中的数相互不同,那么我们就可以直接RMQ获得区间最小值下标。

    在二分p的过程中,我们这样来判断mid是否合法:

    询问1~mid 区间两个数组中的最小值下标是否一致,如果不一致直接返回false,否则 以最小值下标minid为分界点递归处理1minid,minid+1mid。这个过程是O(n)的

    所以总体时间复杂度是 O( n* log n )

    细节见代码:

    #include<iostream>
    using namespace std;
    const int maxn=2e5+10;
    int n;
    int a[maxn],b[maxn];
    int sa[maxn][20],sb[maxn][20],mn[maxn];
    void init()
    {
        mn[0]=-1;
        for (int i=1;i<=n;i++)
        {
            mn[i]=((i & (i-1))==0) ? mn[i-1]+1 : mn[i-1];
            sa[i][0]=a[i];
            sb[i][0]=b[i];
        }
        for (int j=1;j<=mn[n];j++)
            for (int i=1;i+(1<<j)-1<=n;i++)
            {
                sa[i][j]=min(sa[i][j-1],sa[i+(1<<(j-1))][j-1]);
                sb[i][j]=min(sb[i][j-1],sb[i+(1<<(j-1))][j-1]);
            }
    }
    int ida[maxn];
    int idb[maxn];
    int rqa(int L,int R)
    {
        int k=mn[R-L+1];
    //    cout<<"a "<<min(sa[L][k],sa[R-(1<<k)+1][k])<<endl;
        return ida[min(sa[L][k],sa[R-(1<<k)+1][k])];
    }
    int rqb(int L,int R)
    {
        int k=mn[R-L+1];
    //    cout<<"b "<<min(sb[L][k],sb[R-(1<<k)+1][k])<<endl;
        return idb[min(sb[L][k],sb[R-(1<<k)+1][k])];
    }
    bool pan(int l,int r)
    {
        if(l>=r)
        {
            return 1;
        }
        int w=rqb(l,r);
        int q=rqa(l,r);
        if(w!=q)
        {
            return 0;
        }else{
            return pan(l,w-1)&&(pan(q+1,r));
        }
    }
    bool check(int mid)
    {
    //    bool res=1;
        return pan(1,mid);
    }
    int main(){
        while(~scanf("%d",&n)){
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
                ida[a[i]]=i;
            }
            for(int i=1;i<=n;i++){
                scanf("%d",&b[i]);
                idb[b[i]]=i;;
            }
            init();
            int l=1;
            int r=n;
            int mid;
            int ans=1;
            while(l<=r)
            {
                mid=(l+r)>>1;
                if(check(mid))
                {
                    l=mid+1;
                    ans=mid;
                }else{
                    r=mid-1;
                }
     
            }
            printf("%d
    ",ans);
        }
    }
    
    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    hive笔记
    hive数据倾斜的解决办法
    Kafka笔记7
    kafka笔记6
    Kafka笔记5
    kafka笔记4(2)
    kafka笔记4
    Kafka笔记3
    kafka笔记2
    kafka笔记1
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/11209227.html
Copyright © 2020-2023  润新知