题解一
因为是从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 ;
}
还有一个笛卡尔树的做法,这是官方给的做法 (待续)