第 242 场周赛

第 242 场周赛

5763. 哪种连续子字符串更长

题目链接

  • 模拟

模拟

分别记录最长的连续 1 的个数和最长连续 0 的个数

class Solution {
public:
    bool checkZeroOnes(string s) {
        int max_one = 0, max_zero = 0;
        int s0 = 0, s1 = 0;
        for (size_t i = 0; i < s.size(); ++i) {
            if (s[i] == '0') s0++, s1 = 0;
            else s1++, s0 = 0;
            max_one = max(max_one, s1);
            max_zero = max(max_zero, s0);
        }
        
        return max_one > max_zero;
    }
};

5764. 准时到达的列车最小时速

题目链接

  • 二分查找

二分查找

最小速度是 1,最大可能需要的速度是 max(最大距离,最后站距离 / 最后一站需要的最少时间),然后直接二分判断即可

class Solution {
public:
    bool is_arrived(int v, const vector<int>& dist, double hour) {
        double sum_ti = 0.0;
        for (size_t i = 0; i < dist.size() - 1; ++i) {
            // dist[i] / v 向上取整
            int ti = (dist[i] + v - 1) / v;
            sum_ti += ti;
        }
        sum_ti += (dist.back() * 1.0 / v);
        return sum_ti <= hour;
    }
    
    int minSpeedOnTime(vector<int>& dist, double hour) {
        if (dist.size() - 1 >= hour) return -1;
        
        int max_v = -1;
        for (size_t i = 0; i < dist.size(); ++i) max_v = max(max_v, dist[i]);
        if (hour - (int)hour > 0) {
            max_v = max(max_v, (int)(dist.back() / (hour - (int)hour)) + 5);
        }
        int min_v = 1;

        while (min_v < max_v) {
            int mid_v = (min_v + max_v) / 2;
            if (is_arrived(mid_v, dist, hour)) {
                max_v = mid_v;
            } else {
                min_v = mid_v + 1;
            }
        }
        return min_v;
    }
};
  • 整数除以整数向上取整的技巧:
    ⌈ a b ⌉ = ⌊ a + b − 1 b ⌋ \left\lceil\frac{a}{b}\right\rceil=\left\lfloor\frac{a+b-1}{b}\right\rfloor ba=ba+b1

5765. 跳跃游戏 VII

  • 队列
  • 动态规划

队列

首先如果序列的最后一个元素是 1,则表示一定不能到达,否则:

  • 首先将第一个元素 0,所能跳跃的区间范围加入队列
  • 依次遍历序列中的元素,如果遇到零元素,判断该元素与队首区间的位置关系:
    • 如过队列为空,表示该元素不可到达,且后续元素也均不可到达,直接返回 false
    • 如果该元素的位置在队首区间的左边,表示该元素不可到达,但是后续可到达区间中可能还存在零元素
    • 如果该元素在队首区间的右边,将队首区间出队,该元素继续和剩下的区间比较
    • 如果该元素在队首区间范围内,表示该元素可到达,直接将该元素可到达的区间范围加入队列(注意:加入的区间不可以超出序列的范围
  • 如果整个过程中出现队列为空,则返回false,否则最后返回 true
class Solution {
public:
    bool canReach(string s, int minJump, int maxJump) {
        if (s.back() == '1') return false;
        
        queue<pair<int, int> > que;
        while (!que.empty()) que.pop();
        
        que.push(make_pair(minJump, maxJump));
        for (size_t i = 1; i < s.size(); ++i) {
            if (s[i] == '0') {
                while (!que.empty()) {
                    pair<int, int> front = que.front();
                    if (front.first > i) break;
                    else if (front.second < i) {
                        que.pop();
                    } else {
                        if (i + minJump < s.size())
                            que.push(make_pair(i + minJump, min(i + maxJump, s.size())));
                        break;
                    }
                }
                if (que.empty()) return false;
            }
        }
        return true;
    }
};

动态规划

首先还是如果序列的最后一个元素是 1 表示一定不能到达。

否则令 f [ i ] f[i] f[i] 表示是否可以到达位置 i i i f [ i ] = 1 f[i] = 1 f[i]=1 表示可以到达:

  • f [ i ] = 1 f[i] = 1 f[i]=1 当且仅当序列 s [ i ] = 0   a n d   f [ i − m a x J u m p , i − m i n J u m p ] s[i] = 0 \ and \ f[i - maxJump, i - minJump] s[i]=0 and f[imaxJump,iminJump] 中存在元素为 1
  • 判断 f [ i − m a x J u m p , i − m i n J u m p ] f[i - maxJump, i - minJump] f[imaxJump,iminJump] 范围内是否存在元素 1 可以使用前缀和实现
class Solution {
public:
    bool canReach(string s, int minJump, int maxJump) {
        if (s.back() == '1') return false;
        
        int len = s.size();
        int f[len + 5], sm[len + 5];
        memset(f, 0, sizeof f);
        memset(sm, 0, sizeof sm);

        f[1] = sm[1] = 1;
        for (int i = 2; i <= len; ++i) {
            if (s[i - 1] == '0' && i - minJump > 0) {
                int r = i - minJump;
                int l = max(1, i - maxJump);
                f[i] = (sm[r] - sm[l - 1] > 0);
            }
            sm[i] = sm[i - 1] + f[i];
        }
        return f[len];
    }
};

1872. 石子游戏 VIII

题目链接

  • 博弈类型的动态规划

博弈类型的动态规划

在任意一名玩家进行操作之后,剩余的所有石子的价值总和不会发生变化。

对于每一步操作,玩家可以把最左侧的枚石子进行价值合并,并获得与价值等价的分数。因此,最左侧的石子的价值一定是 stones 的某一个前缀和,即玩家在每一轮获得的分数一定是初始数组 stones 的某一个前缀和。

f [ i ] f[i] f[i] 表示当前选手可以选择的下标 u u u [ i , n ) [i, n) [i,n) 时,与对手分数的最大差值。

最大差值 = 当前选手的分数 - 对手的分数,而不是 (当前选手的分数 - 对手分数)的绝对值

那么现在考虑当前选手是否选择第 i i i 个元素:

  • 选择: f [ i ] = p r e [ i ] − f [ i + 1 ] f[i] = pre[i] - f[i + 1] f[i]=pre[i]f[i+1]

    • pre[i] 表示当前选手选择了第 i i i 号位置的元素之后可以获得的分数
    • f [ i + 1 ] f[i + 1] f[i+1] 表示,对手从 [ i + 1 , n ) [i+1, n) [i+1,n) 可以获得的最大分数差。

    假设当前从 [ i , n ) [i, n) [i,n) 进行选择的选手为 A,下一次 B 将从 [ i + 1 , n ) [i+1, n) [i+1,n) 进行选择,而 B 是足够聪明的,为了缩小与 A 之前选择的分差,一定会尽可能拉大之后选择的分差,而 f [ i + 1 ] f[i + 1] f[i+1] 此时可以看作是 B 作为先手的情况, f [ i + 1 ] = S c o r e B − S c o r e A f[i + 1] = Score_B - Score_A f[i+1]=ScoreBScoreA 的最大值,则:
    f [ i ] = pre ⁡ [ i ] (  当前选择获得的分数  ) + S c o r e A ( A 之后选择获得的分数  ) − S c o r e B ( B  之后选择获得的分数  ) . f[i]=\operatorname{pre}[i](\text { 当前选择获得的分数 })+Score_{A}(A \text {之后选择获得的分数 })-Score_{B}(B \text { 之后选择获得的分数 }). f[i]=pre[i]( 当前选择获得的分数 )+ScoreA(A之后选择获得的分数 )ScoreB(B 之后选择获得的分数 ).

  • 不选择: f [ i ] = f [ i + 1 ] f[i] = f[i + 1] f[i]=f[i+1],即当前选手不选择位置为 i i i 的元素,那么最大差值就为从 i + 1 i + 1 i+1 开始选择可以获得的最大差值。

综上: f [ i ] = m a x ( f [ i + 1 ] ,   p r e [ i ] − f [ i + 1 ] ) f[i] = max(f[i + 1], \ pre[i] - f[i + 1]) f[i]=max(f[i+1], pre[i]f[i+1])

class Solution {
public:
    int stoneGameVIII(vector<int>& stones) {
        int n = stones.size();
        for (int i = 1; i < n; ++i) stones[i] += stones[i - 1];

        int dp[n + 5];
        memset(dp, 0, sizeof dp);
        dp[n - 1] = stones[n - 1];
        for (int i = n - 2; i >= 0; --i) {
            dp[i] = max(dp[i + 1], stones[i] - dp[i + 1]);
        }
        return dp[1];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值