A

在这里插入图片描述
题解一

因为是从1-p,所以可以维护两个递增且比a[i]小的栈,如果过程中两个栈的元素数量不一样多,说明到此位置时,最小值的位置不相同。

上面这个我没看懂原因,说的也很潦草,但是不得不让人配服的是,他还真就是对的。
他的这个代码还可以从模拟的角度来看,尝试一下,就会发现,他的代码还真就是模拟的过程(虽然我不知道我当时怎么没有模拟对)

#include <iostream>
#include <stack>
using namespace std;
const int N = 1e5 + 10 ;
stack<int> sta , stb ;
int a[N] , b[N] ;
int main()
{
    int n ;
    while(cin >> n)
    {
      for(int i = 1 ; i <= n ;i ++) cin >> a[i] ;
      for(int i = 1 ; i <= n ;i ++) cin >> b[i] ;
        while(sta.size()) sta.pop() ;
        while(stb.size()) stb.pop() ;
        sta.push(0) , stb.push(0) ;
        int ans = 0 ;
        for(int i = 1 ;i <= n;i ++)
        {
            while(!sta.empty() && sta.top() > a[i]) sta.pop() ;
            sta.push(a[i]) ;
            while(!stb.empty() && stb.top() > b[i]) stb.pop() ;
            stb.push(b[i]) ;
            if(sta.size() == stb.size()) ans = i ;
            else break ;
        }
        cout << ans << endl ;
    }
}

另一种比较简单的做法就是
如果第i个数之前都是处理好的,然后对于第i个数,有四种情况,增加第i个数,影响的区间是[j,i] , j 属于1 到i - 1
分析第i个数,然后与前面的数a[j] 一一比较,如果如果数组a与数组b的比较结果不一致,也就是(a[i] > a[j] && b[i] < b[j]) || (a[i] < a[j] && b[i] > b[j])这两种情况之一,也就代表了,走向趋势不一样,直接就停止,然后可以输出答案了,也可以标志一下,a[i] 和a[j] 的关系还有两种 ,一个是 a[i] < a[j] && b[i] < b[j] ,也就是这个数比之前的a[j] 小, 那么对于区间[j , i] 影响就是最小的数变成了第i个,这个情况完全符合题意,如果a[i] > a[j] && b[i] > b[j] , 那么较小的数一定不是a[i] , 也就是第i个数完全没有价值了,比之前那个还没有用,因为之前每个区间最小的,还是第[j , i] 区间最小的,可以仔细想一想,所以这种情况可以直接break了
我记得这个做法是当时我再网上学的一篇,它说的更详细,但是找不到了

#include <iostream>
using namespace std;
int n ;
const int N = 5e5 + 10 ;
int a[N] , b[N] ;
int main()
{
    while(cin >> n)
    {
        for(int i = 1 ;i <= n;i ++) cin >> a[i] ;
        for(int i = 1 ;i <= n;i ++) cin >> b[i] ;
        bool flag = true ;
        int ans = n ;
        for(int i = 1;i <= n;i ++)
        {
            for(int j = i - 1;j ;j --)
                 if((a[i] > a[j] && b[i] < b[j]) || (a[i] < a[j] && b[i] > b[j]))
                 {
                     flag = false ;
                     break ;
                 }
                 else if(a[i] > a[j] && b[i] > b[j]) break ;
            if(!flag)
            {
                ans = i - 1 ;
                break ;
            }
        }
        cout << ans << endl ;
    }
    return 0 ;
}

还有一个笛卡尔树的做法,这是官方给的做法 (待续)

每次做题提醒自己:题目到底有没有读懂,有没有分析彻底、算法够不够贪心、暴力够不够优雅。
原文地址:https://www.cnblogs.com/spnooyseed/p/12870912.html