题目大意:等价数组定义为(1≤l≤r≤m)中,所有的子区间都满足最小值下标相等,找出最大的m。
题解:我们要找到最大的m,就要保证两个数组的所有子区间最小值下标相等
所以用一个单调栈来维护一个单调递增的序列,栈底为最小值,保证最小值下标相等,以及栈中元素相同
即可保证子区间最小值下标相等
例如:ABCDE
假设C是最小值,A这个区间肯定是可以,AB这个区间肯定是要满足递增或者递减
ABC这个区间就已经满足,因为最小值就是C,同理ABCD,ABCDE,BC,BCD,BCDE,CD,CDE满足。
然后就是DE,如果两个数组不满足递增或递减,那么栈中元素必定不同,那么m就是D下标,反之就是E。•
C++代码
#include<bits/stdc++.h> using namespace std; const int maxn=200050; int a[maxn],b[maxn]; int main(int argc, char const *argv[]) { 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]; stack<int> s1,s2; int flag = 0; for(int i = 1;i <= n ; i++){ while(!s1.empty() && s1.top() > a[i]) s1.pop(); while(!s2.empty() && s2.top() > b[i]) s2.pop(); s1.push(a[i]);s2.push(b[i]); cout << s1.size() << " " << s2.size() << endl; if(s1.size() != s2.size()){ printf("%d ", i -1); //goto out; flag = 1;break; } }if(!flag) printf("%d ", n); } return 0; }
官方题解
做法 1
• 题中的“equivalent”等价于笛卡尔树相同
• 二分答案,比较两个前缀的笛卡尔树 O(n log n)
笛卡尔树:点击此处
做法 2
• 对于数组 a,定义 lasta
(i) = max { j : j < i and aj > ai
}
• 如果 lasta = lastb,那么数组 a 和 b“equivalent”
证明:n, last(n), last(last(n)), ... 是笛卡尔树的最右路径,递归构造
• 单调队列求 last 并比较 O(n)