Bike loves looking for the second maximum element in the sequence. The second maximum element in the sequence of distinct numbers x1, x2, ..., xk (k > 1) is such maximum element xj, that the following inequality holds: .
The lucky number of the sequence of distinct positive integers x1, x2, ..., xk (k > 1) is the number that is equal to the bitwise excluding OR of the maximum element of the sequence and the second maximum element of the sequence.
You've got a sequence of distinct positive integers s1, s2, ..., sn (n > 1). Let's denote sequence sl, sl + 1, ..., sr as s[l..r] (1 ≤ l < r ≤ n). Your task is to find the maximum number among all lucky numbers of sequences s[l..r].
Note that as all numbers in sequence s are distinct, all the given definitions make sence.
The first line contains integer n (1 < n ≤ 105). The second line contains n distinct integers s1, s2, ..., sn (1 ≤ si ≤ 109).
Print a single integer — the maximum lucky number among all lucky numbers of sequences s[l..r].
5 5 2 1 4 3
7
5 9 8 3 5 7
15
For the first sample you can choose s[4..5] = {4, 3} and its lucky number is (4 xor 3) = 7. You can also choose s[1..2].
For the second sample you must choose s[2..5] = {8, 3, 5, 7}.
题意:刚开始都错了题意,只是把第一个样例模拟了一下,做完题才知道理解的题意不符合第二个样例,就有搞了一遍题意:要找到所有子序列中最大的lucy number,lucky number 就是一个子序列中最大值与最小值的异或;
思路:很多子序列的第一大和第二大的值是相同的,比如第一个样例的 5 2 1,5 2 。所以我们就找每个值作为最大值的左宽右宽,这就用到了单调栈(单调递减栈是以自己位最大值找最大的区间)了,用单调栈先画柱状图,就像树状数组我们先画一下树状数组的那个树;
例如:
10 8 3 5 9 11
-------------------------------------------------------------------------------------------
左右宽: (1,4)(1,3)(1,0)(2,0)(3,0)(6,0)
10与8比较,最大,第二大;然后向右推移8的右宽+1那么多位
10与9比较,最大,第二大;然后向右推移9的右宽+1那么多位
10与11比较,第二大,最大,一旦遇到比自己大的,就i++,即开始8与后面的比较
........
上述模拟;
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
int a[N],w[N],L[N],R[N];
int sumor[N],q[N];
int n,h;
void get_lr(int n)
{
int top=0;
stack<int> st;
while(!st.empty()) st.pop();
memset(q,0x3f,sizeof(q));
for(int i=1; i<=n+1; i++)
{
if(i!=n+1)
h=a[i];
else
h=inf-1;
if(h<q[top])
{
q[++top]=h;
w[top]=1;
L[i]=1;
}
else
{
int cnt=0;
while(h>=q[top])
{
int id=st.top();
R[id]=cnt;
cnt=cnt+w[top--];
st.pop();
}
q[++top]=h;
w[top]=cnt+1;
L[i]=cnt+1;
}
st.push(i);
}
}
int main()
{
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
get_lr(n); //得到每个位置的左右宽
int maxx=-1;
for(int i=1; i<n; i++)
{
int index=i+1;
while(a[i]>a[index])
{
maxx=max(maxx,a[i]^a[index]);
index=index+R[index]+1;
if(index>n)
break;
}
if(index>n)
continue;
maxx=max(maxx,a[i]^a[index]);
}
printf("%d\n",maxx);
return 0;
}