A Equivalent Prefixes
求对于序列a、b满足1<=l<<=r<<q所有相同区间的最小值下标相同的最大q
对于元素a[i],如果a[i]满足,前提条件是a[i-1]一定满足,因为1~i包含1~(i-1)的所有区间,那么就是从左到右扫,找到第一个不符合的i,那个i-1就是结果。
对于每个元素暴力枚举显然不行,是O(n^2)。一定需要前面的信息来处理当前的i,我们知道对于i-1成立,那么只要包含a[i]元素的所有区间满足就可以。
记a[k]为之前序列的最小值
(1)a[i]<a[k],那么所有要求区间的下标就是i。
(2)a[i]>a[k],那么涉及到<=最小值元素a[k]的区间一下标一定是k,对于不涉及的,在这个范围内找新的最小值a[k],那么涉及到a[k]的就是新的k,一直递归到最后,就处理出了每个区间的最小值。
如果序列b和序列a的步调不一致,那么就失败,输出结果。
比赛的时候想到这里,但是不知道怎么处理这个东西,下来看到说是单调栈,发现这个题算是单调栈的裸题了。单调栈维护一个单调增的序列,当两个栈的步调不一致时失败,得到最大q
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+5; 4 int a[maxn]; 5 int b[maxn]; 6 int main(){ 7 int n; 8 while(cin>>n){ 9 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 10 for(int j=1;j<=n;j++) scanf("%d",&b[j]); 11 stack <int> s1;stack <int> s2; 12 s1.push(1);s2.push(1); 13 int flag=1; 14 for(int i=2;i<=n;i++){ 15 while(!s1.empty()&&a[i]<a[s1.top()]&&b[i]<b[s2.top()]&&!s2.empty()){ 16 17 s1.pop();s2.pop(); 18 } 19 if(s1.empty()) 20 { 21 s1.push(i);s2.push(i); 22 }else if((a[i]>a[s1.top()]&&b[i]>b[s2.top()])) 23 { 24 s1.push(i);s2.push(i); 25 } 26 else 27 { 28 flag=0; 29 cout <<i-1<<endl; 30 break; 31 } 32 } 33 if(flag) cout <<n<<endl; 34 } 35 return 0; 36 }