题意:
RMQ(u,l,r)意为数组u在[l,r]区间最小值的下标。
题目要求找到最大值p使得:RMQ(u,l,r)=RMQ(v,l,r) for all 1≤l≤r≤m 即任意区间内的RMQ相同。
思路1(单调栈):
分析:
只要两个数组的每个元素的左边第一个比它小的数的位置相同,就能满足任意区间的RMQ相同。
代码:
#include<cstdio> #include<string> #include<cstring> #include<math.h> #include<stack> #include<algorithm> using namespace std; const int N=1e5+10; int a[N],b[N],n; stack<pair<int,int> > s1,s2; int main(){ while(~scanf("%d",&n)){ for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) scanf("%d",&b[i]); while(!s1.empty()) s1.pop(); while(!s2.empty()) s2.pop(); s1.push(make_pair(0,0)); s2.push(make_pair(0,0)); int ans=0; for(int i=1;i<=n;i++){ while(!s1.empty()&&s1.top().first>a[i]){ s1.pop(); } while(!s2.empty()&&s2.top().first>b[i]){ s2.pop(); } if(s1.top().second==s2.top().second){ ans=i; }else{ break; } s1.push(make_pair(a[i],i)); s2.push(make_pair(b[i],i)); } printf("%d\n",ans); } return 0; }
思路2:笛卡尔树
分析:
题中的“equivalent”等价于笛卡尔树相同,分别对两个数组建笛卡尔树,从头开始比较每个元素,如果两棵笛卡尔树的当前元素i的父亲都是i-1或者当前元素i的左孩子相同,那么两棵笛卡尔树相同。一直比较到不同处,于是可得最大值p。
代码:
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 100010; typedef struct node{ int key, val; int f, l, r; bool operator < (node t) const{ return key < t.key; } }node; node T1[MAXN],T2[MAXN]; int stack[MAXN],top,vis[MAXN]; int create(int n,node *T){ top=1; stack[top]=1; for(int i=2; i<= n;i++){ while(top>0&&T[i].val<T[stack[top]].val) //小根堆则改成小于 top--; if(top>0){//右链中的节点 T[i].f=stack[top]; T[i].l=T[stack[top]].r; T[T[stack[top]].r].f=i; T[stack[top]].r=i; stack[++top]=i; }else{// 根节点 T[stack[1]].f=i; T[i].l=stack[1]; stack[++top]=i; } } return stack[1]; } int main() { int n; while(~scanf("%d",&n)){ memset(T1, 0, sizeof(T1)); memset(T2, 0, sizeof(T2)); for(int i = 1; i <= n; i++){ scanf("%d",&T1[i].val); T1[i].key=i; } for(int i = 1; i <= n; i++){ scanf("%d",&T2[i].val); T2[i].key=i; } int root1 = create(n,T1); int root2 = create(n,T2); int ans=1; for(int i=2;i<=n;i++){ if(T1[i].f==i-1&&T2[i].f==i-1||T1[i].l==T2[i].l) ans++; else break; } printf("%d\n",ans); } return 0; }
总结:
单调栈的做法更加直接,笛卡尔树的做法其实利用的也是单调栈的思想,所以其实大可不必建笛卡尔树,直接用单调栈来做。以上两份AC代码,单调栈只用了119ms,而笛卡尔树用了1552ms。