Maximum Xor Secondary(单调栈好题)

Maximum Xor Secondary

CodeForces - 280B

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

55 2 1 4 3

Output

7

Input

59 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}.

题意:给你一串数,问你这一串数的任意子串中的最大值和次大值的异或最大值为多少。

题解:

  因为一个数可以是很多个区间的最大值,一个数也可以是很多个区间的次大值,所以我们可以以数为研究对象而非一个个区间。

  第一种做法:

        从前往后和从后往前各跑一遍单调栈,每次求的是以当前值为次大值,之前一个比它大的值为最大值,然后这两个值异或。因为单调栈求的就是这个数向左或者向右找第一个比它大的值的位置。所以这个数的位置和栈顶元素的位置构成的区间中,这个数和栈顶元素就是该区间里的次大值和最大值。

附代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
using namespace std;
const int maxn=1e5+10;
int ans;
stack<int>s;
stack<int>s2;
int a[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=0;i<n;i++)
    {
        while(!s.empty()&&a[s.top()]<a[i])
        {
            s.pop();
        }
        if(!s.empty())
            ans=max(ans,a[i]^a[s.top()]);
        s.push(i);
    }
    for(int i=n-1;i>=0;i--)
    {
        while(!s2.empty()&&a[s2.top()]<a[i])
        {
            s2.pop();
        }
        if(!s2.empty())
        {
            ans=max(ans,a[i]^a[s2.top()]);
        }
        s2.push(i);
    }
    printf("%d\n",ans);
    return 0;
} 

第二种做法:

      %大佬,思路差不多,只是只用求一遍单调栈就可以。从后往前求一遍单调栈然后记录一下对于每一个值它右边第一个比它大的值的位置。然后遍历一遍,每次可以同时求出该数作为最大值和次大值的异或值。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
stack<int> s;
int r[maxn];
int a[maxn];
int main()
{
    int n,ans;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d",&a[i]);
    for(int i=n-1;i>=0;i--)
    {
        while(!s.empty()&&a[s.top()]<a[i])//找每个数右边第一个比它大的数的下标
        {
            s.pop();
        }
        if(s.empty())
        {
            r[i]=n;
        }
        else
        {
            r[i]=s.top();
        }
        s.push(i);
    }
    ans=0;
    int t;
    for(int i=0;i<n;i++)
    {
        int j=i+1;
        while(j<n)
        {
            t=a[i]^a[j];
            if(t>ans)
            {
                ans=t;
            }
            if(a[j]>a[i])
            {
                break;
            }
            j=r[j];
        }
    }
    printf("%d\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/1013star/p/9985414.html

时间: 2024-11-09 04:31:36

Maximum Xor Secondary(单调栈好题)的相关文章

Codeforces Round #172 (Div. 1) BMaximum Xor Secondary 单调栈

//给一个长度为N的个不相同的序列,找出所有区间中最大值和第二大数的异或值最大的值 //对于所有区间只需要找其最大值和第二大数,所以对于很多区间的结果是重复的 //对于每一个数,它起作用的区间只有在其前面最多只有一个数是大于它的 //可以用一个单调递减栈来做,对于每一个新的数a[i],在它前面第一个大于它的数a[j] //和第二个大于它的数之间的数到a[i]的区间的数的最大值和第二大数为a[j] , a[i] //只需要找a[i],a[j]的所有区间所有情况 #include<cstdio>

单调栈模板题 luogu P2659

题目链接:https://www.luogu.org/problem/P2659 实际上就是要我们求出每个数字左右两边第一个小于它的数字位置,然后两个位置所在的开区间长度乘以这个数字,取最大值输出. 因为是求两边第一个小于a[i]的数字,所以我们弄一个递增(其实是不减小就可以了,可以有相同大小的元素)的单调栈,从栈底到栈顶的数字是依次增大的,在求的过程中要始终保持递增的性质.我们每次在数字入栈时求出数字左边第一个小于它的数字位置,在出栈的时候求出右边第一个小于它的数字位置,为什么是这样,看下面,

[leetcode 85. 最大矩形] 单调栈--84题的简单扩展

题目描述 给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积. 示例: 输入: [ ["1","0","1","0","0"], ["1","0","1","1","1"], ["1","1","1","

Codeforces Round #172 (Div. 2)---D. Maximum Xor Secondary(RMQ + 二分)

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 sequenc

[poj3250]单调栈 Bad Hair Day

解题关键:将每头牛看到的牛头数总和转化为每头牛被看到的次数,然后用单调栈求解,其实做这道题的目的只是熟悉下单调栈 此题为递减栈 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<stack> 6 #include<iostream> 7 using namespace std; 8 typedef lo

poj2796 Feel Good 单调栈

题意:给定一个序列,需要找出某个子序列S使得Min(a[i])*Σa[i] (i属于S序列)最大 正解:单调栈 这题的暴力还是很好想的,只需3分钟的事就可以码完,以每个点拓展即可,但这样的复杂度是O(n^2)的,肯定会TLE 以暴力的思想作为基础,再进行深层次思考,考虑每个点往周围拓展的时候,都要走到最远的地方停下来,也就是说会有一个左上限,一个右上限(命名为:pre.next),不难发现再枚举5.4.3.2.1这个序列的时候,每次都要往左扫描到最左边,显然这是做了重复的事情,于是机智的我马上想

[luoguP2659] 美丽的序列(单调栈)

传送门 单调栈大水题 l[i] 表示 i 能扩展到的左边 r[i] 表示 i 能扩展到的右边 ——代码 1 #include <cstdio> 2 #include <iostream> 3 #define LL long long 4 5 const int MAXN = 2000002; 6 int n, t; 7 LL ans, a[MAXN], s[MAXN], l[MAXN], r[MAXN]; 8 9 inline int read() 10 { 11 int x =

[51nod1102]面积最大的矩形(单调栈||预处理)

题意:求序列上某区间最小值乘区间长度的最大值. 解题关键:很早就在<挑战程序设计竞赛>中见过了,单调栈模板题,注意弹栈时如何处理后面的元素. 法一:单调栈 #include<bits/stdc++.h> using namespace std; typedef long long ll; stack<int>s; ll a[50002]; int main(){ int n; cin>>n; for(int i=0;i<n;i++) cin>&g

bzoj1012最大数maxnumber——单调栈

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1012 单调栈水题:用了一下lower_bound二分. 代码如下: #include<iostream> #include<cstdio> #include<algorithm> using namespace std; int m,d,len,a[200005],sta[200005],top,lst; char s[5]; int main() { scanf