牛牛的魔法值 题解

牛牛的魔法值

http://www.nowcoder.com/questionTerminal/4d7d8a61ad2f4c9b9f130a35a97b49f5

题目大意:

给你一个长度为n的序列,问你,这个序列的所有连续子序列中,子序列的最大值和次大值的异或和最大是多少?

分析:

我们直接枚举所有连续子序列肯定布星,我们换一个枚举方向。

我们考虑枚举子序列的次大值,那么,我们只需要找到一个当前枚举的点的值大的那个点作为最大值即可。

我们注意到,因为我们枚举的是次大值,所以它所处在的子序列中,比它大的点有且只有一个。所以,我们找到这个点左边,离它最近的比它大的点的值和这个点右边,离它最近的比它大的点的值,那么连续子序列的最大值必然是这两个值中的一个。我们每个都算下取最大即可。

至于如果求这两个值,随便搞搞就行,基本就不需要动脑了/x

我是用的st表+二分搞的。

代码:

class Solution {
public:
    int s[100001][20];
    inline int calc(int l,int r){
        int len=(r-l+1),now=0;
        while(len>=(1<<(now+1))){
            ++now;
        }
        return max(s[l][now],s[r-(1<<now)+1][now]);
    }
    int solve(int n, vector<int>& a) {
        for(int i=0;i<n;++i){
            s[i][0]=a[i];
        }
        int lon=1;
        for(int i=1;i<20;++i){
            lon<<=1;
            for(int j=0;j<n;++j){
                int r=j+lon-1;
                if(r>n){
                    break;
                }
                s[j][i]=max(s[j][i-1],s[r-(lon/2)+1][i-1]);
            }
        }
        int ans=0;
        for(int i=0;i<n;++i){
            int l=0,r=i-1,res=-1;
            while(l<=r){
                int mid=(l+r)>>1;
                if(calc(mid,i-1)>a[i]){
                    res=mid;l=mid+1;
                }else{
                    r=mid-1;
                }
            }
            if(res!=-1){
                ans=max(ans,(a[i]^a[res]));
            }
            l=i+1,r=n-1,res=-1;
            while(l<=r){
                int mid=(l+r)>>1;
                if(calc(i+1,mid)>a[i]){
                    res=mid,r=mid-1;
                }else{
                    l=mid+1;
                }
            }
            if(res!=-1){
                ans=max(ans,(a[i]^a[res]));
            }
        }
        return ans;
    }
};

我们还可以使用单调队列,这样,复杂度就只有了!

代码:

class Solution {
public:
    int que[100001],l=1,r=0;
    int solve(int n, vector<int>& a) {
        que[++r]=a[1];int ans=0;
        for(int i=2;i<=n;++i){
            while(l<=r&&que[r]<=a[i]){
                --r;
            }
            if(l<=r){
                ans=max(ans,(a[i]^que[r]));
            }
            que[++r]=a[i];
        }
        l=1,r=0;
        que[++r]=a[n];
        for(int i=n-1;i;--i){
            while(l<=r&&que[r]<=a[i]){
                --r;
            }
            if(l<=r){
                ans=max(ans,(a[i]^que[r]));
            }
            que[++r]=a[i];
        }
        return ans;
    }
};

事实上,只需要使用单调栈就行了qwq

代码:

class Solution {
public:
    int sta[100001],top=0;
    int solve(int n, vector<int>& a) {
        sta[++top]=a[1];int ans=0;
        for(int i=2;i<=n;++i){
            while(top&&sta[top]<=a[i]){
                --top;
            }
            if(top){
                ans=max(ans,(a[i]^sta[top]));
            }
            sta[++top]=a[i];
        }
        top=0;
        sta[++top]=a[n];
        for(int i=n-1;i;--i){
            while(top&&sta[top]<=a[i]){
                --top;
            }
            if(top){
                ans=max(ans,(a[i]^sta[top]));
            }
            sta[++top]=a[i];
        }
        return ans;
    }
};
全部评论

相关推荐

04-02 10:09
门头沟学院 Java
用微笑面对困难:这里面问题还是很多的,我也不清楚为啥大家会感觉没啥问题。首先就是全栈开发实习9个月的内容都没有java实习生的内容多,1整个技术栈没看出太核心和难点的内容,感觉好像被拉过去打杂了,而且全栈基本上很容易被毙。里面能问的bug是在太多了比如L:继承 BaseMapper 可直接使用内置方法’。请问你的 BaseMapper 是如何扫描实体类注解如果瞬时产生 100 个上传任务,MySQL 的索引设计是否会有瓶颈?你做过分库分表或者索引优化吗?全栈的内容可以针对动态难点去搞,技能特长写在下面吧,你写了这么多技能,项目和实习体现了多少?你可以在项目里多做文章然后把这个放下去,从大致来看实习不算太水,有含金量你也要写上内容针对哨兵里面的节点变化能问出一万个问题,这个很容易就爆了。
提前批简历挂麻了怎么办
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务