リンク: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);
}
}