8.13信息学集训_数据结构

news/2024/9/19 9:22:27/文章来源:https://www.cnblogs.com/hellohebin/p/18356116

目录
  • P1981 [NOIP2013 普及组] 表达式求值
  • P1449 后缀表达式
  • P5788 【模板】单调栈
  • P1886 滑动窗口 /【模板】单调队列
  • P1901 发射站
  • P1540 [NOIP2010 提高组] 机器翻译
  • P2085 最小函数值
  • P6033 [NOIP2004 提高组] 合并果子 加强版
  • P1631 序列合并
  • P2251 质量检测
  • P1305 新二叉树
  • B3631 单向链表
  • P1739 表达式括号匹配
  • P1996 约瑟夫问题
  • P1808 单词分类
  • B3616 【模板】队列
  • P3378 【模板】堆
  • P4715 【深基16.例1】淘汰赛

P1981 [NOIP2013 普及组] 表达式求值

  • P1981 [NOIP2013 普及组] 表达式求值

给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值。
输入一行需要计算的表达式,表达式中只包含数字、加法运算符‘+’和乘法运算符‘×’,且没有括号,所有参与运算的数字均为 0 到 pow(2,31)-1之间的整数。输入数据保证这一行只有 0-9、+、× 这12种字符。
输出一个整数,表示这个表达式的值,当答案长度多于4位时,请只输出最后4位,前导0不输出。

输入样例:1+1*3+4
输出样例:8

【分析】模拟/栈
先观察输入数据的格式,一定是:a+b+b+b...
那么可以考虑先读入 a,后面死循环读入 +b,这样就可以轻松完成数据分割。

由于有 *+,可以将 * 先处理了,后面对于 + 直接累加即可。
构建一个数字栈,遍历字符串,数字直接入栈;如果是运算符,将当前栈顶元素 ab进行计算,同时pop,计算的结果push。
最后累加栈内全部元素即可。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
stack<long long> sta;
int a,b,ans=0, mod=10000;  char ch;
int main() {cin>>a;  a %= mod;  sta.push(a);while(cin>>ch>>b) {b %= mod;if(ch=='*') {a = sta.top();  sta.pop();sta.push(a*b%mod);} else if(ch=='+') { sta.push(b); }}while(!sta.empty()) {ans += sta.top(), sta.pop();ans %= mod;}cout<<ans%mod;    return 0;
}

P1449 后缀表达式

  • P1449 后缀表达式

所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优先级)。
如:3*(5–2)+7 对应的后缀表达式为:3.5.2.-*7.+@。
'@'为表达式的结束符号,'.'为操作数的结束符号。字符串长度在1000内。

输入格式:后缀表达式
输出格式:表达式的值

输入样例:3.5.2.-*7.+@
输出样例:16

【分析】模拟/栈
先观察输入数据的格式,一定是:a.a.+@
每个数字后面有一个 .,可以据此进行数据分割。

构建一个数字栈,遍历字符串,数字直接入栈;
如果是运算符,将顺序取出两个栈顶元素 a,b 进行计算,计算的结果push。
最后栈顶元素就是答案。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
stack<int> sta;  int a,b,c;  char ch;
int main(){while((ch=getchar())!='@'){if(ch<='9' && ch>='0'){a=a*10+ch-'0';}else if(ch=='.'){sta.push(a);  a=0;}else {a=sta.top(),sta.pop();b=sta.top(),sta.pop();if(ch=='+'){ c = b+a; }else if(ch=='-'){ c = b-a; }else if(ch=='*'){ c = b*a; }else if(ch=='/'){ c = b/a; }sta.push(c);  a=b=0;}}cout<<c<<endl;  return 0;
}

P5788 【模板】单调栈

  • P5788 【模板】单调栈

给出项数为 \(n\) 的整数数列 \(a_{1 \dots n}\)
定义函数 \(f(i)\) 代表数列中第 \(i\) 个元素之后第一个大于 \(a_i\) 的元素的下标,即 \(f(i)=\min_{i<j\leq n, a_j > a_i} \{j\}\)。若不存在,则 \(f(i)=0\)

试求出 \(f(1\dots n)\)

输入格式:第一行一个正整数 \(n\)。第二行 \(n\) 个正整数 \(a_{1\dots n}\)
输出格式:一行 \(n\) 个整数 \(f(1\dots n)\) 的值。

输入样例 输出样例
5
1 4 2 3 5
2 5 4 5 0

【数据范围】对于 \(100\%\) 的数据,\(1 \le n\leq 3\times 10^6\)\(1\leq a_i\leq 10^9\)

【分析】

  • 求每个元素右边第一个大于该元素的值的下标。
  • 维护一个单调栈,可以画一下下面这个图。

image

上图是从左向右遍历的单调递减栈

也可以维护一个从右向左遍历的单调递增栈。

#include<bits/stdc++.h>
using namespace std;
const int N=3e6+10;
typedef long long LL;
int n,a[N],ans[N];
int st[N],h=0;int main(){scanf("%d", &n);for(int i=1; i<=n; i++) scanf("%d", &a[i]);// 从左向右 : 维护一个单减栈for(int i=1; i<=n; i++){while(h && a[st[h]] < a[i] ){ans[st[h]] = i;h--;}st[++h] = i;}/* // 从右向左 : 维护一个单增栈 for(int i=n; i>=1; i--){while(h && a[st[h]] <= a[i]) h--;ans[i] = st[h];st[++h] = i;} */for(int i=1; i<=n; i++) printf("%d ", ans[i]);return 0;
}

P1886 滑动窗口 /【模板】单调队列

  • P1886 滑动窗口 /【模板】单调队列

有一个长为 \(n\) 的序列 \(a\),以及一个大小为 \(k\) 的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。

例如:The array is \([1,3,-1,-3,5,3,6,7]\), and \(k = 3\)

输入格式: 输入一共有两行,第一行有两个正整数 \(n,k\)。第二行 \(n\) 个整数,表示序列 \(a\)
输出格式:输出共两行,第一行为每次窗口滑动的最小值;第二行为每次窗口滑动的最大值

输入样例 输出样例
8 3
1 3 -1 -3 5 3 6 7
-1 -3 -3 -3 3 3
3 3 5 5 6 7

【数据范围】\(1\le k \le n \le 10^6\)\(a_i \in [-2^{31},2^{31})\)

【分析】考虑两个问题

  1. 如何确定窗口大小:可以通过下标求差完成
  2. 如何确定窗口内的最值:可以利用单调队列完成

这里为了便于理解,我们画一个样例图

image

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int a[N], q[N], fr=0, ta=-1;int main(){int n,m; cin>>n>>m;for(int i=1; i<=n; i++) cin>>a[i];for(int i=1; i<=n; i++){while(fr<=ta && i-q[fr]+1 > m) ++fr;while(fr<=ta && a[q[ta]]>=a[i]) --ta;q[++ta]=i;if(i>=m) cout<<a[q[fr]]<<" ";}cout<<endl;fr=0, ta=-1;for(int i=1; i<=n; i++){while(fr<=ta && i-q[fr]+1 > m) ++fr;while(fr<=ta && a[q[ta]]<=a[i]) --ta;q[++ta]=i;if(i>=m) cout<<a[q[fr]]<<" ";}return 0;
}

P1901 发射站

  • P1901 发射站

某地有 \(N\) 个能量发射站排成一行,每个发射站 \(i\) 都有不相同的高度 \(H_i\),并能向两边(两端的发射站只能向一边)同时发射能量值为 \(V_i\) 的能量,发出的能量只被两边最近的且比它高的发射站接收。显然,每个发射站发来的能量有可能被 \(0\)\(1\)\(2\) 个其他发射站所接受。

请计算出接收最多能量的发射站接收的能量是多少。

输入格式:第 \(1\) 行一个整数 \(N\)。第 \(2\)\(N+1\) 行,第 \(i+1\) 行有两个整数 \(H_i\)\(V_i\),表示第 \(i\) 个人发射站的高度和发射的能量值。
输出格式:输出仅一行,表示接收最多能量的发射站接收到的能量值。答案不超过 32 位带符号整数的表示范围。

输入样例 输出样例
3
4 2 
3 5 
6 10
7

【数据范围】\(1\le N\le 10^6,1\le H_i\le 2\times 10^9,1\le V_i\le 10^4\)

【分析】

  • 法1:直接暴力模拟,左右查找合适的值,可以过 40%,会 TLE。
  • 法2:维护单调栈(单调递减栈:栈底到栈顶元素单调递减)

image

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e6+10,INF=0x3f3f3f3f;
int n,h[N],v[N],st[N],head=0;
LL ans[N];void slove1() { // 预计 TLEfor(int i=1; i<=n; i++) {int l=i-1, r=i+1;while(l>0 && h[l]<=h[i]) l--;while(r<=n && h[r]<=h[i]) r++;ans[l]+=v[i], ans[r]+=v[i];}
}
void slove2() { // 维护一个单调栈for(int i=1; i<=n; i++) {while(head && h[st[head]] < h[i]) {ans[i] += v[st[head]], head--;}ans[st[head]] += v[i];st[++head] = i;}
}
int main() {scanf("%d",&n);for(int i=1; i<=n; i++) scanf("%d%d",&h[i],&v[i]);slove1();for(int i=1; i<=n; i++) ans[1]=max(ans[1],ans[i]);printf("%lld\n",ans[1]);return 0;
}

P1540 [NOIP2010 提高组] 机器翻译

  • P1540 [NOIP2010 提高组] 机器翻译

P2085 最小函数值

  • P2085 最小函数值

P6033 [NOIP2004 提高组] 合并果子 加强版

  • P6033 [NOIP2004 提高组] 合并果子 加强版

P1631 序列合并

  • P1631 序列合并

P2251 质量检测

  • P2251 质量检测

P1305 新二叉树

  • P1305 新二叉树

B3631 单向链表

  • B3631 单向链表

P1739 表达式括号匹配

  • P1739 表达式括号匹配

P1996 约瑟夫问题

  • P1996 约瑟夫问题

n 个人围成一圈,从第一个人开始报数,数到 m 的人出列,再由下一个人重新从 1 开始报数,数到 m 的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。

输入格式:输入两个整数 n,m(1≤m,n≤100)。
输出格式:输出一行 n 个整数,按顺序输出每个出圈人的编号。

输入样例:10 3
输出样例:3 6 9 2 7 1 8 5 10 4
点击查看代码
#include<bits/stdc++.h>
using namespace std;
queue<int> que;
int main(){int n,m,cnt=1; cin>>n>>m;for(int i=1; i<=n; i++) que.push(i);while(!que.empty()){if(cnt<m){que.push(que.front());que.pop();  cnt++;}else if(cnt==m){cout<<que.front()<<" ";que.pop();  cnt=1;}} return 0;
}

P1808 单词分类

  • P1808 单词分类

【题目描述】
两个单词可以分为一类当且仅当组成这两个单词的各个字母的数量均相等。
例如 "AABAC",它和 "CBAAA" 就可以归为一类,而和 "AAABB" 就不是一类。
现在Oliver有N个单词,所有单词均由大写字母组成,每个单词的长度不超过100。
你要告诉Oliver这些单词会被分成几类。

【输入格式】输入文件的第一行为单词个数N,以下N行每行为一个单词。
【输出格式】输出文件仅包含一个数,表示这N个单词分成的类数

输入样例 输出样例
3
AABAC
CBAAA
AAABB
2
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+1;
char s[N][101];
int main(){int n; cin>>n;for(int i=1; i<=n; i++){scanf("%s", s[i]);sort(s[i], s[i]+strlen(s[i]));}map<string,int> m;for(int i=1; i<=n; i++){m.insert(pair<string,int>(s[i],1));}printf("%d", m.size());return 0;
}

B3616 【模板】队列

  • B3616 【模板】队列

P3378 【模板】堆

  • P3378 【模板】堆

给定一个数列,初始为空,请支持下面三种操作:

  1. 给定一个整数 x,请将 x 加入到数列中。
  2. 输出数列中最小的数。
  3. 删除数列中最小的数(如果有多个数最小,只删除 1 个)。

输入格式:第一行是一个整数,表示操作的次数 n。
接下来 n 行,每行表示一次操作。每行首先有一个整数 op 表示操作类型。
若 op=1,则后面有一个整数 x,表示要将 x 加入数列。
若 op=2,则表示要求输出数列中的最小数。
若 op=3,则表示删除数列中的最小数。如果有多个数最小,只删除 1 个。

输出格式:对于每个操作 2,输出一行一个整数表示答案。

输入样例 输出样例
5
1 2
1 5
2
3
2
2
5
点击查看代码
#include<iostream>
#include<queue>
using namespace std;
priority_queue<int, vector<int>, greater<int> > pq;
//priority_queue<int, vector<int>, less<int> > pq;
int main(){int n;  cin>>n;for(int i=1; i<=n; i++){int f; cin>>f;if(f==1){int x;  cin>>x;  pq.push(x);}else if(f==2){cout<<pq.top()<<endl;}else if(f==3){pq.pop();}} return 0;
}

P4715 【深基16.例1】淘汰赛

  • P4715 【深基16.例1】淘汰赛

有 2^n(n≤7) 个国家参加世界杯决赛圈且进入淘汰赛环节。
我经知道各个国家的能力值,且都不相等。能力值高的国家和能力值低的国家踢比赛时高者获胜。
1 号国家和 2 号国家踢一场比赛,胜者晋级。3 号国家和 4 号国家也踢一场,胜者晋级……晋级后的国家用相同的方法继续完成赛程,直到决出冠军。
给出各个国家的能力值,请问亚军是哪个国家?

输入样例 输出样例
3
4 2 3 1 10 5 9 7
1
点击查看代码
#include<iostream>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
int main() {int n; cin>>n; n = pow(2, n); // n=1<<n;queue<pair<int, int> > que;for(int i=1; i<=n; i++) {int a; cin>>a; que.push(make_pair(i, a));}while( que.size() > 2 ){pair<int, int> x,y;x = que.front(); que.pop();y = que.front(); que.pop();if(x.second > y.second) que.push(x);else que.push(y);}pair<int, int> x,y;x = que.front(); que.pop();y = que.front(); que.pop();if(x.second > y.second) cout<<y.first;else cout<<x.first;return 0;
}

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

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

相关文章

Windows Server 2025 中文版、英文版下载 (Inside Preview, updated Aug 2024) - 下一代 Windows 11 Server

Windows Server 2025 中文版、英文版下载 (Inside Preview, updated Aug 2024) - 下一代 Windows 11 ServerWindows Server 2025 中文版、英文版下载 (Inside Preview, updated Aug 2024) - 下一代 Windows 11 Server Windows Server 2025 正式版发布在即 请访问原文链接:http…

如何让您的 .NET应用程序更智能-- 请参加 8.20 的 .NET Conf--Focus on AI

Microsoft 将于 2024 年 8 月 20 日举办免费的 .NET Conf: Focus on AI。该虚拟活动为开发人员提供了如何集成 .NET 和 AI 以增强应用程序开发和用户体验的见解,其中包括专家和行业领导者的会议。 为什么你不应该错过这个活动? .NET Conf: Focus 系列由全年举行的小型现场活…

如何让您的 .NET应用程序更智能-- 请参加 8.20 的 .NET Conf ndash; Focus on AI

Microsoft 将于 2024 年 8 月 20 日举办免费的 .NET Conf: Focus on AI。该虚拟活动为开发人员提供了如何集成 .NET 和 AI 以增强应用程序开发和用户体验的见解,其中包括专家和行业领导者的会议。为什么你不应该错过这个活动?.NET Conf: Focus 系列由全年举行的小型现场活动…

如何让您的 .NET应用程序更智能-- 请参加 8.20 的 .NET Conf -- Focus on AI

Microsoft 将于 2024 年 8 月 20 日举办免费的 .NET Conf: Focus on AI。该虚拟活动为开发人员提供了如何集成 .NET 和 AI 以增强应用程序开发和用户体验的见解,其中包括专家和行业领导者的会议。为什么要参加?.NET Conf: Focus 系列由全年举行的小型现场活动组成。8 月 20…

读零信任网络:在不可信网络中构建安全系统17无控制器架构

无控制器架构1. 建立系统框图 1.1. 实现零信任网络的第一步重要工作是建立系统框图 1.2. 系统框图能够帮助我们透彻地理解内部网络和外部网络间的通信模式,有助于系统通信信道的设计 1.3. 对于现有的网络来说,建议首先利用日志工具来记录网络流量,然后观察通信信息的流向,一…

计算机体系结构技术杂谈(下)

计算机体系结构技术杂谈(下) 2.8 加速Transformer:稀疏注意力加速器分析 1. 稀疏注意力加速器简介 近年来, Transformer模型在深度学习的各个领域,包括自然语言处理、图像分类、图像及语音生成等方面,都取得了远超于传统神经网络模型的表现。最近的ChatGPT和各类基于Tran…

计算机体系结构技术杂谈(中)

计算机体系结构技术杂谈(中) 例2:进阶算法 基础算法无法解决中断恢复的问题,即假如有两个写寄存器的操作,指令1,指令2,可能乱序执行时指令2的结果已经将写回了寄存器,但是指令1还未执行,此时发生中断后,从指令1重新开始执行,就会重新进行两次写入,将会发生错误。 只…

算子计算与调度杂谈

算子计算与调度杂谈 9.4.1 GPU内核驱动分析概述 不同CPU相比,GPU中包含了大量的并行计算单元,适合处理像素,矩阵,坐标等大量同类型的数据,因此,很多LINUX上的应用程序为了能够利用GPU的加速功能,都试图和GPU直接打交道,因此,系统中可能有多个组件或者程序同时使用GPU,…

misc一题

题目一开始给了个docx文件 无法打开 010editor发现为pk开头 后缀名改为zip 翻目录在1/page路径下找到使用notepad++查看 在unicodestring字段后进行拼接得到flag flag{xps?Oh,Go0d}

C#项目—模拟考试

C#模拟考试软件 开发了一个《模拟考试》的小软件,此小软件练习的目的主要是为了体会编程思想,深度理解高内聚、低耦合,掌握编程思维逻辑的大招,告别垃圾代码,重点体会编程之美,练习时长30分钟;开发一个项目之前,切记不要打开程序就写代码,首先要做的就是分析项目,从项…

基于直流潮流的IEEE30电力系统停电分布及自组织临界性分析matlab仿真

1.课题概述 详细的讲,我们的这个算法的安如下的步骤进行:步骤1:k=k+1,通过慢动态过程中的几个公式,对Pmax,Fmax进行更新;步骤2:考虑随机因素进行线路的断开,以一个随机概率来随机断开一条支路;步骤3:根据慢动态计算得到的参数开始进行慢动态仿真;步骤4:在慢动态仿…

基于多路径路由的全局感知网络流量分配优化算法matlab仿真

1.程序功能描述 2.测试软件版本以及运行结果展示MATLAB2022a版本运行3.核心程序figure; bar(alpha); text(0.5,0.8,用户1,8节点); text(1,0.9,用户2,8节点); text(1.5,0.8,用户1,11节点); text(2,0.9,用户2,11节点); axis([0,3,0,1.2])figure; bar(beta); text(0.6,0.3,用…