2019牛客暑期多校训练营(第一场)

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 }

 

posted @ 2019-07-19 09:49  Chuhanjing  阅读(267)  评论(0编辑  收藏  举报