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 1lrm1≤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 pnp≤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.
* 1n1051≤n≤105 * 1ai,bin1≤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.
题意大概就是两个数组,找最大的p,使对于1到p的所有子区间都保证最小值的下标相同;
这时我们就可以发现,如果a[i]<a[i+1]&&b[i]<b[i+1],则a[i+1]和b[i+1]对之前所有子区间都不构成影响,因为总有min(a[1],a[i])比a[i+1]小;
那么我们可以线性的考虑,对于a[i]<a[i+1]&&b[i]<b[i+1]这种情况直接跳过,其他的情况则往前寻找第一个比a[i](b[i])小的数,如果下标相等则符合;如果下标不等则说明了不能取,证明如下:
往前寻找第一个比a[i]小的数的下标为k1,同理b为k2,如果k1!=k2,则在(min(k1,k2),i)这个子区间上不成立,反正成立(都推到i了,则前面的肯定经过了一样的推理证明成立,可知所有子区间均成立)
找前面的第一个比自身小的数可以用单调栈的思想来标记(由于某人不会,我粗略说一下这题的用法),每次找到当前项符合的值,记录下标,到下次往前找的时候可以直接跳到这一项的符合值;
比如设当前为第k项,找到了第m项是符合的,则下次第i项(i>k)往前搜索搜到k时可直接跳到第m项。
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define INF 0x3fffffff
#define maxn 100005
int n,m,k,t;
int a[maxn],b[maxn],num1[maxn],num2[maxn];
int main(){
    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]);
        a[0]=b[0]=0;
        num1[1]=num2[1]=0;
        for(int i=2;i<=n;i++){
            int k1=i-1,k2=i-1;
            while(a[i]<a[k1])
                k1=num1[k1];
            num1[i]=k1;
            while(b[i]<b[k2])
                k2=num2[k2];
            num2[i]=k2;
            if(num1[i]!=num2[i]){
                printf("%d\n",i-1);
                break;
            }
            if(i==n)
                printf("%d\n",n);
        }
    }
}