題意:
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。