| 题号 | A | B | C | D | E | F | G | H | I | J |
| 状态 | Ο | . | . | . | Ø | Ο | . | . | . | Ο |
题意:给出两个序列$rmq$相等的定义:任意子区间最小值相等,然后给出$a、b$两个数组,求最长的前缀相等序列长度。
题解:我们考虑前$k$个数字已经是相等序列了,这个时候我们加入第$k+1$个元素$x$,如果$x$比第$k$个元素大,会发现这绝对不会使序列变的不合法。当$x$比第$k$个小时,我们发现$x$会影响从$k$往前开始,从后往前直到出现第一个比$x$小的数字。在这个位置会改变最小值的关系,所以我们用一个权值单调递增的单调栈来维护序列,如果每个地方影响的位置都相同,则合法,否则就break。
#include<bits/stdc++.h> #define clr(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; int n; const int maxn=100010; int a[maxn],b[maxn]; struct node{ int val,pos; }sta1[maxn],sta2[maxn]; int top1,top2; int main(){ while(cin>>n){ top1=top2=0; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } int ans=0; int flag=1; for(int i=1;i<=n;i++){ scanf("%d",&b[i]); while(top1!=0&&a[i]<sta1[top1].val){ top1--; } sta1[++top1].val=a[i]; sta1[top1].pos=i; int x=i-sta1[top1-1].pos; while(top2!=0&&b[i]<sta2[top2].val){ top2--; } sta2[++top2].val=b[i]; sta2[top2].pos=i; int y=i-sta2[top2-1].pos; if(x==y&&flag){ ans++; }else{ flag=0; } } printf("%d\n",ans); } }