以上の2019頭の牛オフサマースクールキャンプを(最初の)等価プレフィックス(STの半分+テーブル+パーティション)

リンク:https://ac.nowcoder.com/acm/contest/881/A
出典:牛オフネットワーク

等価プレフィックスの
時間制限:C / C ++ 2秒、及び他の言語4秒の
スペースの制限:1048576K C / C ++ 524288K、他の言語
IO形式64:%のLLDの
タイトル説明を
2つのアレイuがあり、V mのそれぞれの場合にのみ異なる要素が呼び出される等価IF
R&LTの
M
Q

U

L

R&LT

=
R&LT
のM
Q

V

L

R&LT

RMQ(U、L、R&LT)のすべてのためのRMQ =(V、L、R&LT)
。1

L
≤の
R&LTの

M
1≦ l≤r≤m R&LT M Q W







L

R

RMQ(W、L、R)は、のうちの最小要素のインデックスを示し
、W
L

wは
L

  • 1

    ...

    W
    Rの
    WL、WL + 1、...、WR。
    アレイの別個の要素を含んでいるので、最小限の定義は明白です。

ボボは、2つの配列AとBそれぞれのnの別個の要素を有します。最大数の検索
のp
≤を
N
p≤nここで
、{ 1 2 ... P } 、{A1、A2、...、AP}及び{ B 1 B 2 ... BのP } {B1、B2、 ···、BP}は等価である。输入描述:入力は、いくつかのテストケースで構成され、ファイルの終わりで終了します。


























各テストケースの最初の行は、整数nを含んでいます。
2行目は、N個の整数含ま1 2 ... n個のA1、A2、...、。第三のラインは、n整数含まB 1 B 2 ... Bのn個のB1、B2、...、BNを。






















  • 1

    N

    10
    5
    1≤n≤105
  • 1
    I bはiはN 1≤ai、bi≤n







  • { 1 2 ... N } 、{A1、A2、...、}異なります。











  • {
    B
    1

    B
    2

    ...

    Bの
    N
    }
    {B1、B2、...、BN}異なります。
  • 和のN-ん超えない
    5。
    ×
    10
    5。
    5×105。
    出力説明:
    各テストケースの場合は、検索結果を表し整数を印刷します。
    例1つの
    インプット
    コピー
    2
    1 2
    2 1
    3。
    2 1 3
    3 1 2。
    5。
    3 1。 2. 4. 5
    。5 4 3 2 1
    出力
    コピー
    。1
    。3
    。4

質問が意図される:
あなたは(1 <= p <=数pを見つけてみましょう、あなたのサイズnの、Bは、二つの配列を与えるために 、N)、 いずれか一つのセクションの、B 1〜Pアレイの最小値となるよう同じ規格。
アイデア:

Pは、互いに異なるアレイ内の数は、我々は、直接最小間隔添字をRMQ得ることができるので、我々は最初に、後続RMQを容易にするために、前処理STテーブル列A、Bで使用される、単調値を知ることは容易です。

二部Pの過程で、我々はこの半ば合法性を判断します。

1〜2つの極小配列インデックスの値、そうでない場合は、直接、そうでない場合、添字minid境界点再帰プロセス1〜minid、minid + 1〜中間の最小値がfalseを返す場合、中間セクションが尋ね。このプロセスは、O(N)であります

したがって、Oの全体的な時間計算量(N *ログ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\n",ans);
    }
}

おすすめ

転載: www.cnblogs.com/qieqiemin/p/11209227.html