前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LeetCode周赛2021年5月9日

LeetCode周赛2021年5月9日

作者头像
韩旭051
发布2021-05-11 11:45:52
4860
发布2021-05-11 11:45:52
举报
文章被收录于专栏:刷题笔记刷题笔记

太久不写代码了 第一次有空 做LeetCode周赛 不是 下标越界 就是 暴力超时

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

或者是 明明很简单的题目 就是懒得写 比较麻烦 就不动手

在这里插入图片描述
在这里插入图片描述

看别人的分享 学习一下

第一题 活着的人 最多的年份

class Solution {
public:
    int yr[3000];
    int maximumPopulation(vector<vector<int>>& logs) {
        for (vector<int> log : logs) {
            int b = log[0];
            int d = log[1];
            for (int i = b; i < d; ++i) ++yr[i];
        }
        int ans = 1950;
        int m = 0;
        for (int i = 1950; i <= 2050; ++i) {
            if (yr[i] > m) {
                m = yr[i];
                ans = i;
            }
        }
        return ans;

    }
};

第二题就是双指针

class Solution {
public:
    int yr[3000];
    int maximumPopulation(vector<vector<int>>& logs) {
        for (vector<int> log : logs) {
            int b = log[0];
            int d = log[1];
            for (int i = b; i < d; ++i) ++yr[i];
        }
        int ans = 1950;
        int m = 0;
        for (int i = 1950; i <= 2050; ++i) {
            if (yr[i] > m) {
                m = yr[i];
                ans = i;
            }
        }
        return ans;

    }
};

第三题 空间换时间存储中间值 动态规划

class Solution {
public:
    int a[200001], stk[200001];
    int l[200001], r[200001];
    long long s[200001];
    int maxSumMinProduct(vector<int>& nums) {
        int n = (int )nums.size();
        for (int i = 0; i < n; i ++) {
            a[i + 1] = nums[i];
        }
        for (int i = 1; i <= n; i ++) s[i] = s[i - 1] + a[i];
        stk[0] = 0;
        int top = 0;
        long long ans = 0;
        for (int i = 1; i <= n; i ++) {
            while (top && a[stk[top]] >= a[i]) -- top;
            l[i] = stk[top] + 1;
            stk[++ top] = i;
        }
        top = 0; stk[0] = n + 1;
        for (int i = n; i >= 1; i --) {
            while (top && a[stk[top]] >= a[i]) -- top;
            r[i] = stk[top] - 1;
            ans = max(ans, 1LL * a[i] * (s[r[i]] - s[l[i] - 1]));
            stk[++ top] = i;
        }
        return ans % ((int )1e9 + 7);
    }
};

子数组最小乘积的最大值 ?链接:link

?思路:这种题目属于基础的笛卡尔树的题目,但是这里我们换一种方式论述。

由于所有的值都是正整数,所以区间长度在最小值不变的情况下越大越好。 我们把这个数组按照最小值进行划分。 容易知道如果把当前的最小值作为答案区间的最小值, 取整个数组的话答案一定最大, 所以此时就可以用最小值和整个数组的和更新一次答案。 两个被分出来的数组由于跨出这个数组就会碰到一个比数组里面所有数都还要小的数字, 必然比划分之前的数组答案还要小, 所以这两个数组里面的答案只能在数组里面。

我们惊讶的发现这就是一个递归求解的问题。 由于每一次分割都会少一个值, 可以发现计算的次数就是数组长度。

现在只有最后一个问题:找到最小值所在的位置。 为了方便编写,我们可以考虑使用 ST 表进行维护。 假如你知道怎么用 ST 表求出区间最小值, 那么我们只需要在去求完之后判断两个数字哪个更小, 使用这个方式进行更新即可。

作者:tiger2005 链接:https://leetcode-cn.com/circle/discuss/7QlTIV/view/Vo980u/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
public:
    int st[100010][20],st2[100010][20];
    int LOG2[100010];
    vector<int> n;
    vector<long long> m;
    int que(int l,int r){
        int m=LOG2[r-l+1];
        int ll=st2[l][m], rr=st2[r-(1<<m)+1][m];
        if(n[ll]<n[rr]) return ll;
        return rr;
    }
    long long ans=0;
    void dfs(int l,int r){
        if(l>r) return;
        if(l==r){
            ans=max(ans, 1ll*n[l] * n[l]);
            return;
        }
        int p=que(l, r);
        ans=max(ans, 1ll * n[p] * (m[r]-(l==0?0:m[l-1])));
        dfs(l,p-1);dfs(p+1,r);
    }
    int maxSumMinProduct(vector<int>& nums) {
        LOG2[1]=0;n=nums;
        m.resize(nums.size());
        m[0]=nums[0];
        for(int i=1;i<(int)nums.size();i++)
            m[i]=m[i-1]+nums[i];
        for(int i=2;i<=1e5;i++) LOG2[i]=LOG2[i>>1]+1;
        for(int i=0;i<(int)nums.size();i++)
            st[i][0]=nums[i],st2[i][0]=i;
        for(int i=1;(1<<i)<=(int)nums.size();i++)
            for(int j=0;j+(1<<i)<=nums.size();j++){
                st[j][i]=min(st[j][i-1], st[j+(1<<(i-1))][i-1]);
                if(st[j][i] == st[j][i-1])  st2[j][i]=st2[j][i-1];
                else    st2[j][i]=st2[j+(1<<(i-1))][i-1];
            }
        dfs(0, nums.size()-1);
        return ans % (1000000007);
    }
};

作者:tiger2005
链接:https://leetcode-cn.com/circle/discuss/7QlTIV/view/Vo980u/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

前缀和+单调栈 经典单调栈题目。因为数组元素都为正数,所以子数组最小值的元素位置一定时,子数组长度越大,得到的乘积越大。

我们利用单调栈可以求出每个元素作为最小值时的最长子数组,再利用预计算的前缀和求得乘积。最后取所有乘积的最大值即可。

时间复杂度\mathcal{O}(N)O(N)。 空间复杂度\mathcal{O}(N)O(N)。

using ll = long long;
const ll MOD = 1e9 + 7;

class Solution {
public:
    int maxSumMinProduct(vector<int>& nums) {
        int n = nums.size();
        vector<ll> s(n + 1);
        for (int i = 1; i <= n; ++i)
            s[i] = s[i - 1] + nums[i - 1];
        
        vector<int> l(n, 0), r(n, n - 1);
        stack<int> st;
        for (int i = 0; i < n; ++i) {
            while (!st.empty() && nums[st.top()] > nums[i]) {
                r[st.top()] = i - 1;
                st.pop();
            }
            st.push(i);
        }
        st = stack<int>();
        for (int i = n - 1; i >= 0; --i) {
            while (!st.empty() && nums[st.top()] > nums[i]) {
                l[st.top()] = i + 1;
                st.pop();
            }
            st.push(i);
        }
        
        ll ans = 0;
        for (int i = 0; i < n; ++i)
            ans = max(ans, (s[r[i] + 1] - s[l[i]]) * nums[i]);
        
        return ans % MOD;
    }
};

作者:吴自华
链接:https://leetcode-cn.com/circle/discuss/7QlTIV/view/2CLPG9/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

最后一题完全没看 就没有学习价值了 我就 只摘抄前三题

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-05-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 看别人的分享 学习一下
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档