【单调栈】codeforces 280b

time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

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.

Input

The first line contains integer n (1 < n ≤ 105). The second line contains n distinct integers s1, s2, ..., sn (1 ≤ si ≤ 109).

Output

Print a single integer — the maximum lucky number among all lucky numbers of sequences s[l..r].

Examples
input
5
5 2 1 4 3
output
7
input
5
9 8 3 5 7
output
15
Note

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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值