时间限制: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 RMQ(u,l,r)=RMQ(v,l,r)RMQ(u,l,r)=RMQ(v,l,r) for all 1≤l≤r≤m1≤l≤r≤m

where RMQ(w,l,r)RMQ(w,l,r) denotes the index of the minimum element among wl,wl+1,…,wrwl,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≤np≤n where {a1,a2,…,ap}{a1,a2,…,ap} and {b1,b2,…,bp}{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 a1,a2,…,ana1,a2,…,an.
The third line contains n integers b1,b2,…,bnb1,b2,…,bn.

* 1≤n≤1051≤n≤105
* 1≤ai,bi≤n1≤ai,bi≤n
* {a1,a2,…,an}{a1,a2,…,an} are distinct.
* {b1,b2,…,bn}{b1,b2,…,bn} are distinct.
* The sum of n does not exceed 5×1055×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

题意很难懂,但是懂了就发现就是和笛卡尔树的性质是一样的。两种做法

第一种笛卡尔树做法(保存一波模板:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2e5 + 10, mod = 998244353;
int a[maxn], b[maxn], l[2][maxn], r[2][maxn], rt[2], sz[2][maxn];
stack<int> s;
int gao(int n) {
for (int i = 1; i<= n; i++) { // 建立a数组的笛卡尔树
l[0][i] = r[0][i] = 0;
while (!s.empty() && a[i] < a[s.top()])
l[0][i] = s.top(), s.pop();
if (!s.empty())
r[0][s.top()] = i;
s.push(i);
}
while (!s.empty())
rt[0] = s.top(), s.pop();
for (int i = 1; i <= n; i++) { // 建立b数组的笛卡尔树
l[1][i] = r[1][i] = 0;
while (!s.empty() && b[i] < b[s.top()])
l[1][i] = s.top(), s.pop();
if (!s.empty())
r[1][s.top()] = i;
s.push(i);
}
while (!s.empty())
rt[1] = s.top(), s.pop();

for (int i = 1; i <= n; i++) //判断两颗笛卡尔树是否一致
if (l[0][i] != l[1][i] || r[0][i] != r[1][i])
return 0;
return 1;
}
int main(){
int n;
while (~scanf("%d", &n)) {
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= n; i++)
scanf("%d", &b[i]);
int L = 1, R = n;
while (L < R) {
int m = (L + R) / 2;
if (gao(m))
L = m + 1;
else
R = m;
}
if (!gao(L))
L--;
printf("%d\n", L);
}
}

单调栈做法:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back


using namespace std;
typedef long long ll;
const int N=5e5+10;
int a[N],b[N];
int s1[N*4],s2[N*4];
int ls[N*20],rs[N*20];
int ls1[N*20],rs1[20*N];
int cnt;

int main()
{
int n;
while(~scanf("%d",&n)){

for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;++i){
scanf("%d",&b[i]);
}
//printf("b1:%d\n",b[1]);
stack<int>que;
que.push(0);
que.push(1);
int p=1;
for(int i=2;i<=n;++i){
//printf("b:%d\n",b[que.top()]);
//printf("%d %d %d %d\n",a[i],a[que.top()],b[i],b[que.top()]);
if(a[i]>a[que.top()]&&b[i]>b[que.top()]){
p++;
//printf("i:%d\n",i);
que.push(i);
}
else if(a[i]<a[i-1]&&b[i]<b[i-1]){
while(a[que.top()]>a[i]&&b[que.top()]>b[i]){
que.pop();
}
if(a[que.top()]<a[i]&&b[que.top()]<b[i]) {
p++;
//printf("i:%d\n",i);
que.push(i);
continue;
}
else break;
}
else break;

}
printf("%d\n",p);
}

}