首先描述一下 单调栈的作用 如5 2 1 4 3 从左到右入以递减的方式入栈, 遇到大的就出栈,直到栈为空或者出现比它大的数那它就入栈
在这个过程中有一个现象,每个数都会从左到右找第一个比它大的数
那么下面题目来了:
有一串数字 a[1],a[2].....a[n] 问你这里面任意一个区间的最大值和第二大的值的异或值最大是多少;
分析:
显然每个区间枚举太耗费时间了,而且时间上也过不去,那我们可以从值入手(因为值的个数有限),回想上面的单调栈,它可以找到每个数在某一个方向上的第一个大于它的值,
也就相当于把题目要求的情况都枚举了一遍(当然还有从右往左遍历一遍),对栈的操作综合不会超过n次 所以时间复杂度是线性的O(n);
ac代码:
#include<bits/stdc++.h> using namespace std; int main (){ ios::sync_with_stdio(0); cin.tie(0); int arr[100004]; int n; cin>>n; for(int i=1;i<=n;i++) cin>>arr[i]; int ans =0; stack<int> stac; stac.push(arr[1]); for(int i=2;i<=n;i++){ while(!stac.empty()&&arr[i]>stac.top()){ int x=stac.top(); stac.pop(); ans=max(x^arr[i],ans); } stac.push(arr[i]); } while(!stac.empty()) stac.pop(); stac.push(arr[n]); for(int i=n-1;i>=1;i--){ while(!stac.empty()&&arr[i]>stac.top()){ int x=stac.top(); stac.pop(); ans=max(x^arr[i],ans); } stac.push(arr[i]); } cout<<ans<<endl; }