2024蓝桥杯省赛保奖突击班-单调栈、模拟、简单dp_练习题解

P1449 后缀表达式

题目链接: P1449
参考思路:

如果遇到的字符是数字,则将连续的数字转成整数,并把操作数后面的"."过滤掉;如果遇到是字符是运算符,则取出操作数栈栈顶的两个元素进行计算,并把结果压回去;如果是“@”,程序结束,输出栈顶(栈底)元素。

C++参考代码
#include <bits/stdc++.h>
using namespace std;
int n, m,i,j,k, a[1010];
string s;
int getint(){//从字符串中获取一个操作数int n=0;while(s[i]>='0'&& s[i]<='9'){n = n * 10 + s[i++]- 48;}i++; //s[i]= ·过滤操作数后面的“.”return n;return n;
}
void cal(){//取出两个操作数根据运算符进行计算if(s[i] == '+')a[n-1] += a[n];else if(s[i] == '-')a[n-1] -= a[n];else if(s[i] == '*')a[n-1] *= a[n];else if(s[i] == '/')a[n-1] /= a[n];n--, i++;//操作数少一个,字符串后移一位
}
int main(){cin>>s;while(s[i] != '@'){if(s[i]< 48)cal();//遇到运算符则计算else a[++n]= getint();//读取操作数}cout<<a[1];return 0;
}
java参考代码
import java.util.Scanner;public class Main {static int n = 0, i = 0; // 定义静态变量n和istatic int[] a = new int[1010]; // 定义一个静态整数数组a,长度为1010static String s; // 定义静态字符串spublic static void main(String[] args) {Scanner scanner = new Scanner(System.in);s = scanner.nextLine(); // 从标准输入读取一行字符串while (i < s.length() && s.charAt(i) != '@') { // 循环直到字符串结束或遇到'@'if (s.charAt(i) < '0') { // 如果字符不是数字,则是运算符calculate(); // 调用calculate方法进行计算} else { // 如果字符是数字a[++n] = getInt(); // 调用getInt方法获取整数并存储在数组a中}}System.out.println(a[1]); // 输出数组a的第一个元素scanner.close(); // 关闭Scanner对象}static int getInt() { // 从字符串中获取一个整数的方法int num = 0; // 定义并初始化变量numwhile (i < s.length() && s.charAt(i) >= '0' && s.charAt(i) <= '9') { // 循环直到非数字字符num = num * 10 + (s.charAt(i++) - '0'); // 将字符转换为数字并累加到num}if (i < s.length() && s.charAt(i) == '.') { // 如果数字后面跟着一个点'.'i++; // 跳过这个点}return num; // 返回获取到的整数}static void calculate() { // 根据运算符进行计算的方法switch (s.charAt(i)) { // 根据当前字符选择运算符case '+':a[n - 1] += a[n]; // 加法运算break;case '-':a[n - 1] -= a[n]; // 减法运算break;case '*':a[n - 1] *= a[n]; // 乘法运算break;case '/':a[n - 1] /= a[n]; // 除法运算break;}n--; // 用掉一个操作数i++; // 字符串指针后移一位}
}
python参考代码
def getint(s, i):n = 0while i < len(s) and '0' <= s[i] <= '9':n = n * 10 + int(s[i])i += 1i += 1  # 跳过数字后面的句点return n, idef cal(stack, operator):b = stack.pop()a = stack.pop()if operator == '+':stack.append(a + b)elif operator == '-':stack.append(a - b)elif operator == '*':stack.append(a * b)elif operator == '/':stack.append(a // b)  # 使用整数除法def main():s = input()i = 0stack = []while i < len(s) and s[i] != '@':if '0' <= s[i] <= '9':number, i = getint(s, i)stack.append(number)else:cal(stack, s[i])i += 1print(stack[0])if __name__ == '__main__':main()

P1540机器翻译

题目链接: P1540
参考思路:

由于本题数据范围较小,我们可以采用指针的方法来解决。

首先,我们创建两个数组。一个数组 a 用于存储标记。在读入单词 x 时,若当前数组 a 中的第 x 位的标记为 1,则表示该单词在内存中;若标记为 0,则表示该单词不在内存中。这样做可以一步判断读入的单词当前是否在内存中,而不必从头到尾搜索。此外,在存入单词时,只需将数组 a 中的第 x 位的标记从 0 改为 1;在删除内存中的单词 x 时,只需将数组 a 的第 x 位的标记从 1 改为 0。这样一来,我们可以在一步到位,大大降低时间复杂度,提高程序效率。这是本题的关键之一,需要仔细体会和理解。

接着,我们创建另一个数组 b,用于存储内存中的单词,并按读入顺序存入。例如,b[1] 中存储的单词 x 是在时间1存入的。需要注意的是,如果当前读入的单词 x 已经在内存中(即 a[x]==1),则不必存入数组 b 中;只有遇到内存中没有的新单词才需要存入。

然后,我们需要引入两个指针。一个是 l,指向当前内存中最先存入的单词,例如 b[l] 是当前内存中第一个存入的单词。另一个是 r,指向当前内存中最后一个存入的单词,例如 b[r] 是当前内存中最后一个存入的单词。因此,数组 b 的第 l 位到第 r 位存储的就是当前内存中的单词。

当遇到新单词时(即 a[x]==0),情况有两种:

  1. 如果内存未被用完(即 r<=m),则指针 r 向右移一位,在 b[r] 中存入新单词,并将数组 a 中单词 x 的标记改为 1
  2. 如果内存已满(即 r>m),则先删除当前内存中最先存入的单词 b[l]。删除操作不需要太复杂,只需将指针 l 向右移一位,然后再修改数组 ab[l] 位置的标记即可。最后别忘了在 b[r] 中存入新单词 x
c++参考代码
#include <bits/stdc++.h>
using namespace std;
int n,m,x,ans,l,r,a[1005],b[1005];
int main(){cin>>m>>n;l=0;r=0;//初始化两个指针for (int i=1;i<=n;i++){cin>>x;//边读入边做if (a[x]==0) {ans++;r++;b[r]=x;a[x]=1;//因为每次遇到新单词都要做这些操作,不如搬到判断语句外做,这样程序更简洁if (r>m) {l++;a[b[l]]=0;}}}cout<<ans;return 0;
}
java参考代码
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int m = scanner.nextInt(); // 窗口或缓存的最大大小int n = scanner.nextInt(); // 总输入数int[] a = new int[1005]; // 用于检查项目是否在缓存中int[] b = new int[1005]; // 用于存储缓存中的项目(类似队列)int l = 0, r = 0, ans = 0; // l 和 r 是缓存窗口的指针,ans 是唯一项目的计数for (int i = 1; i <= n; i++) {int x = scanner.nextInt(); // 输入项目if (a[x] == 0) { // 如果项目尚未在缓存中ans++; // 增加唯一计数r++;b[r] = x; // 将项目添加到缓存中a[x] = 1; // 将项目标记为在缓存中if (r > m) { // 如果缓存超过其大小l++;a[b[l]] = 0; // 从缓存中移除最旧的项目}}}System.out.println(ans); // 输出唯一项目的计数scanner.close();}
}
python参考代码
m, n = map(int, input().split())  # 同时读取 m 和 n
inputs = list(map(int, input().split()))  # 读取整行输入并转换为整数列表a = [0] * 1005  # 初始化数组 a
b = [0] * 1005  # 初始化数组 b
ans = 0
l = 0
r = 0for x in inputs:  # 直接迭代处理输入的整数列表if a[x] == 0:ans += 1r += 1b[r] = xa[x] = 1if r > m:l += 1a[b[l]] = 0print(ans)

P9290 Decryption

题目链接: p9290
参考思路:

考虑到"最小"和"最大"对于序列的限制,我们可以采用单调栈来优化数组的维护。对于这道题目,我们需要使用两个栈进行维护:一个是严格单调递减的栈(记作 stk1[n]),另一个是单调递增的栈(记作 stk2[n])(关于为何使用这两种单调栈的问题建议配合后面的 AC 代码食用)。

其次,这道题还需要利用动态规划(DP)来求解。我们定义一个一维数组 dp[n],对于任意一个数组下标 idp[i] 表示到 i 坐标处,分割出来的序列全为合法序列的最小分割次数。

然后我们来构思状态转移方程,试想,如果当前坐标 i 后(注意是 i 坐标后,否则状态转移会出问题)需要进行分割以构成合法序列,上一次开始分割的坐标 j 需要尽可能地小才能保证转移出的结果是最小的。

有了这样的想法,这时候就应该与前面提到的单调栈来配合了。由于这道题对数组内的顺序有严格要求,因此在使用单调栈时,栈中存储的不是数组变量的值,而是数组变量的下标。

c++参考代码
#include<bits/stdc++.h>
using namespace std;
int n,a[300005],dp[300005],top1,top2,stk1[300005],stk2[300005];
//stk1:严格单调递减栈 stk2:单调递增栈
int main()
{cin>>n;for(int i = 1; i <= n; i++) scanf("%d",&a[i]);for(int i = 1; i <= n; i++){while(top1 && a[stk1[top1]] <= a[i]) top1--;stk1[++top1] = i;while(top2 && a[stk2[top2]] > a[i]) top2--;stk2[++top2] = i;//维护两个单调栈 dp[i] = dp[*lower_bound(stk2 + 1,stk2 + top2 + 1,stk1[top1 - 1]) - 1] + 1;}cout<<dp[n];return 0;
} 
java参考代码
//注意!java版本500ms左右过不去
import java.util.*;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int[] a = new int[n + 1];int[] mn = new int[n + 1];int[] mx = new int[n + 1];Deque<Integer> mns = new ArrayDeque<>();Deque<Integer> mxs = new ArrayDeque<>();mns.addLast(0); // Initialize with 0 to handle base casemxs.addLast(0);for (int i = 1; i <= n; i++) {a[i] = scanner.nextInt();while (!mns.isEmpty() && a[i] < a[mns.peekLast()]) {mns.removeLast();}while (!mxs.isEmpty() && a[i] >= a[mxs.peekLast()]) {mxs.removeLast();}mn[i] = mns.isEmpty() ? 0 : mns.peekLast(); // Check if empty before accessingmx[i] = mxs.isEmpty() ? 0 : mxs.peekLast(); // Check if empty before accessingmns.addLast(i);mxs.addLast(i);}int res = 0;for (int i = n; i > 0; ) {int j = i;// Ensure that mn[j] is a valid indexwhile (mx[i] < mn[j] && mn[j] > 0) {j = mn[j];}i = j - 1;res++;}System.out.println(res);scanner.close();}
}
python参考代码
此题 Python不合适 正式比赛不会出现这种情况。

P1725 琪露诺

题目链接: P1725
参考思路:

假设f[i]表示跳到第 i 个格子的最优值。

初始状态为f[0]=0,表示在原点的价值为0。

状态转移方程为:
f [ i ] = max ⁡ j ∈ [ i − r , i − l ] { f [ j ] + a [ i ] } f[i] =\max_{j\in[i-r,i-l]}\{f[j]+a[i]\} f[i]=j[ir,il]max{f[j]+a[i]}
最终状态为 max(f[n+1],…,f[n+l]),因为琪露诺最终跳到的区间范围是 [n+1,n+l]。

为了优化这一过程,我们观察到 f[i] 的取值只能由决策区间[ir,il] 转移而来,而 a[i] 是定值,因此我们只需考虑决策区间 [ir,il] 对 f[i] 的影响。

根据动态规划的转移方程,我们需要求决策的最大值。因此,我们可以采用一种数据结构来维护决策的最优值。

考虑到每个f[i] 对应一个决策区间,而区间移动的长度是固定的,这启发我们联想到滑动窗口这个概念。我们可以通过动态维护区间的最大值,从而省去一维枚举决策的时间。

维护区间最值可以使用优先队列或者单调队列两种方式。

首先,考虑优先队列的做法。对于堆中的元素,我们需要使用一个 vis[i] 数组来表示是否在队列中,并检查维护的区间是否超出了决策区间,直到删除堆顶元素使其符合条件为止。

每次移动的操作时间复杂度为 O(logn),因此总时间复杂度为 O(nlogn)。

c++参考代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+50;
int n,l,r,a[N],f[N],vis[N],ans=-1e9,use[N];//use[i]标记f[i]是否合法
priority_queue< pair<int,int> > q;
int main(){cin>>n>>l>>r;for(int i = 1; i <= 2 * n; i++) f[i]=-1e9;for(int i = 0; i <= n; i++) cin>>a[i];for(int i = l; i <= r; i++) use[i]=1;for(int i = 0; i <= n; i++){if(i<l) {q.push(make_pair(-1e9,0));f[i+l]=a[i+l];continue;}int y=q.top().second; if(i-r+l-1>=0) vis[i-r+l-1]=1;while(vis[y]||!use[y]) { q.pop(); if(q.empty()) break; y=q.top().second;} //删除堆顶不合法的决策q.push(make_pair(f[i],i));f[i+l]=q.top().first+a[i+l];if(use[i]) use[i+l]=1;}for(int i = n + 1; i <= n + l; i++) if(use[i]) ans=max(ans,f[i]);cout<<ans;return 0;
}
java参考代码
import java.util.*;public class Main {static final int N = 300050; static int[] a = new int[N];static int[] f = new int[N];static boolean[] vis = new boolean[N];static boolean[] use = new boolean[N];static int ans = Integer.MIN_VALUE; // 相当于 C++ 中的 -1e9public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int l = sc.nextInt();int r = sc.nextInt();Arrays.fill(f, Integer.MIN_VALUE); // 使用 -1e9 初始化 f[]for (int i = 0; i <= n; i++) {a[i] = sc.nextInt();}for (int i = l; i <= r; i++) {use[i] = true;}PriorityQueue<Pair> q = new PriorityQueue<>((x, y) -> y.first - x.first); // 基于第一个元素的最大堆for (int i = 0; i <= n; i++) {if (i < l) {q.offer(new Pair(Integer.MIN_VALUE, 0)); // 入队 -1e9,0f[i + l] = a[i + l];continue;}int y = q.peek().second;if (i - r + l - 1 >= 0) {vis[i - r + l - 1] = true;}while (vis[y] || !use[y]) {q.poll();if (q.isEmpty()) break;y = q.peek().second;}q.offer(new Pair(f[i], i));f[i + l] = q.peek().first + a[i + l];if (use[i]) use[i + l] = true;}for (int i = n + 1; i <= n + l; i++) {if (use[i]) ans = Math.max(ans, f[i]);}System.out.println(ans);sc.close();}static class Pair {int first;int second;public Pair(int first, int second) {this.first = first;this.second = second;}}
}
python参考代码
此题 Python不合适 正式比赛不会出现这种情况。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/811202.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分享2024高校专业建设思路及建设效果

广东泰迪智能科技股份有限公司成立于2013年&#xff0c;是一家专业从事大数据、人工智能等数据智能技术研发、咨询和培训的高科技企业&#xff0c;公司基于十余年的数据智能产业实践经验&#xff0c;构建“产、岗、课、赛、证、文”融通的特色应用型人才培养模式&#xff0c;助…

Unity3D 打空包与远程资源更新详解

前言 在游戏开发过程中&#xff0c;打包和远程资源更新是非常重要的步骤&#xff0c;本文将详细介绍Unity3D中如何进行打空包和远程资源更新。 对惹&#xff0c;这里有一个游戏开发交流小组&#xff0c;希望大家可以点击进来一起交流一下开发经验呀&#xff01; 一、打空包 …

蓝桥杯(填空题)

十四届 B组 日期统计&#xff08;暴力枚举&#xff09; 数据 5 6 8 6 9 1 6 1 2 4 9 1 9 8 2 3 6 4 7 7 5 9 5 0 3 8 7 5 8 1 5 8 6 1 8 3 0 3 7 9 2 7 0 5 8 8 5 7 0 9 9 1 9 4 4 6 8 6 3 3 8 5 1 6 3 4 6 7 0 7 8 2 7 6 8 9 5 6 5 6 1 4 0 1 0 0 9 4 8 0 9 1 2 8 5 0 2 5 3…

深入理解Linux网络工具:netstat命令的高级应用

在Linux系统中&#xff0c;网络管理员经常需要监控和诊断网络连接问题。netstat命令是一个非常强大的工具&#xff0c;它可以显示系统上的网络连接、路由表、接口统计等信息。本文将深入探讨netstat命令的两个常用选项组合&#xff1a;-tlnp和-tnp&#xff0c;并解释它们的区别…

力扣 | 54. 螺旋矩阵

注意按照顺时针方向进行访问元素&#xff0c;以及每次触发的条件只会满足一个&#xff01; public List<Integer> spiralOrder(int [][] matrix){List<Integer> result new ArrayList<>();int m matrix.length;int n matrix[0].length;int row0,col 0;//…

构建第一个ArkTS之声明式UI描述

ArkTS以声明方式组合和扩展组件来描述应用程序的UI&#xff0c;同时还提供了基本的属性、事件和子组件配置方法&#xff0c;帮助开发者实现应用交互逻辑。 创建组件 根据组件构造方法的不同&#xff0c;创建组件包含有参数和无参数两种方式。 说明 创建组件时不需要new运算…

【4】c++多线程技术之高级线程同步技术

1、读写锁&#xff08;std::shared_mutex&#xff09;&#xff08;C17&#xff09; 读写锁&#xff08;std::shared_mutex&#xff09;是C17中引入的一种同步原语&#xff0c;用于允许多个线程同时读取共享数据&#xff0c;但在写入数据时只允许一个线程进行操作。这种锁可以提…

python毕业设计django游泳馆管理系统-flask

游泳馆管理系统具有信息管理功能的选择。游泳馆管理系统采用python技术&#xff0c;基于mysql开发&#xff0c;实现了首页&#xff0c;教练信息&#xff0c;培训信息&#xff0c;交流版块&#xff0c;活动公告&#xff0c;个人中心&#xff0c;后台管理等内容进行管理&#xff…

计算机毕业设计 工厂车间设备管理系统php+vue.js

该系统是以PHP为主要开发语言&#xff0c;集合MySQL数据库技术构建基于Web的以信息为目标的&#xff0c;动态的交互平台 PHP与Apache&#xff0c;MySQL的组合虽然有着诸多优势&#xff0c;但三种出自不同作者的开源软件要能很好的配合工作&#xff0c;需要很多手工配置&#x…

队列.....

假设以带头结点的循环链表表示队列&#xff0c;并且只设一个指针指向队尾结点&#xff0c;但不设头指针。试设计相应的入队和出队算法。 #include <stdio.h> #include <stdlib.h>#define ERROR -1 #define OK 0typedef int QElemType; // 假设队列中元素类型为 in…

WordPress JS Support Ticket插件 RCE漏洞复现

0x01 产品简介 WordPress和WordPress plugin都是WordPress基金会的产品。JS Support Ticket是使用在其中的一套开源票务系统插件。 0x02 漏洞概述 WordPress中的JS Support Ticket插件存在未经上传漏洞,未经身份验证的攻击者可以上传恶意脚本的服务器,执行任意指令,从而获…

【chatGPT】我:在Cadence Genus软件中,出现如下问题:......【4】

我 在Cadence Genus中&#xff0c;tcl代码为&#xff1a;foreach clk $clk_list{ set clkName [lindex $clk_list 0] set targetFreq [lindex $clk_list 1] set uncSynth [lindex $clk_list 4] set clkPeriod [lindex “%.3f” [expr 1 / $targetFreq]] … } 以上代码出现如下…

【JavaEE初阶系列】——网络编程 TCP客户端/服务器 程序实现

目录 &#x1f6a9;TCP流套接字编程 &#x1f36d;ServerSocket API &#x1f36d;Socket API &#x1f36d;TCP服务器 &#x1f36d;TCP客户端 &#x1f6a9;TCP流套接字编程 俩个关键的类 ServerSocket (给服务器使用的类&#xff0c;使用这个类来绑定端口号&#xff0…

设计模式:命令模式

命令模式&#xff08;Command Pattern&#xff09;是一种行为设计模式&#xff0c;它将一个请求封装为一个对象&#xff0c;从而使你可用不同的请求对客户进行参数化&#xff1b;对请求排队或记录请求日志&#xff0c;以及支持可撤销的操作。 定义 命令模式包括以下主要角色&…

C语言程序与设计——工程项目开发

之前我们已经了解了C语言的基础知识部分&#xff0c;掌握这些之后&#xff0c;基本就可以开发一些小程序了。在开发时&#xff0c;就会出现合作的情况&#xff0c;C语言是如何协作开发的呢&#xff0c;将在这一篇文章进行演示。 工程项目开发 在开发过程中&#xff0c;你接到…

LeetCode 1. Two Sum

LeetCode 1. Two Sum 题目描述 给定一个整数数组 nums 和一个整数目标值 target ,请你在该数组中找出 和为目标值 target 的那两个整数&#xff0c;并返回它们的数组下标。 示例1&#xff1a; 输入&#xff1a;nums [2,7,11,15], target 9 输出&#xff1a;[0,1] 解释&…

【算法每日一练]-图论(lca) 最近公共祖先LCA,货车运输

目录 P3379&#xff1a;最近公共祖先LCA 思路&#xff1a; 货车运输 P3379&#xff1a;最近公共祖先LCA 思路&#xff1a; 首先进行的预处理&#xff0c;将所有点的深度和p数组求出来 设置&#xff1a;p[i][j]存的从i向上走2的j次方那么长的路径到的父节点 更深的点走到和…

PostgreSQL入门到实战-第二十二弹

PostgreSQL入门到实战 PostgreSQL中表连接操作(六)官网地址PostgreSQL概述PostgreSQL中self-join命令理论PostgreSQL中self-join命令实战更新计划 PostgreSQL中表连接操作(六) 使用PostgreSQL自联接技术来比较同一表中的行 官网地址 声明: 由于操作系统, 版本更新等原因, 文…

MySQL -- MySQL Connection C中的API介绍

MySQL – MySQL Connection C中的API介绍 文章目录 MySQL -- MySQL Connection C中的API介绍一、接口介绍1.初始化mysql_init()2. 链接数据库mysql_real_connect3.下发mysql命令mysql_query4.获取执行结果mysql_store_result5.获取结果行数和列数6.获取列名mysql_fetch_fields7…

0412备战蓝桥杯,图论复习

1.朴素dijkstra #include<algorithm> #include<iostream> #include<cstring> #include<queue> #include<cmath>using namespace std; const int N 510; int n,m; int g[N][N],dist[N]; bool st[N];int dij(){memset(dist,0x3f,sizeof dist);di…