news 2026/5/13 4:33:40

P2681 众数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
P2681 众数

记录45

#include<bits/stdc++.h> using namespace std; int main(){ int a[1010]={},b[1010]={},cnt[1010]={},n,m,f,x,y; cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; while(m--){ memset(b+1,0,sizeof(b)); memset(cnt+1,0,sizeof(cnt)); cin>>f>>x>>y; if(f==1) a[x]=y; int e=1; if(f==0){ for(int i=x;i<=y;i++){ bool check=1; for(int j=1;j<e;j++){ if(b[j]==a[i]){ check=0; cnt[j]++; } } if(check){ b[e]=a[i]; cnt[e++]++; } } int max_=0,t=0; for(int i=1;i<e;i++){ if(cnt[i]>max_){ max_=cnt[i]; t=b[i]; } if(cnt[i]==max_){ if(b[i]<t) t=b[i]; } } cout<<t<<endl; } } return 0; }

题目传送门https://www.luogu.com.cn/problem/P2681


突破点

现在她需要 Bob 支持询问一个区间内的众数,

👉区间内出现最多的数

还要支持修改一个位置的 ai​。

👉修改指定位置的数字

区间内的众数,如果有多个输出较小的。

👉输出出现最多数字中最小的那一个


思路

  1. 数据不大,直接暴力模拟
  2. 输入数字序列
  3. 判断是输出众数还是修改数字👉修改数字直接改
  4. 一个存放区间内出现数字的数组👉统计出现的数字
  5. 一个存放数字出现个数的数组👉统计数字出现的情况
  6. 比较后输出最小的众数

代码简析

#include<bits/stdc++.h> using namespace std; int main(){ int a[1010]={},b[1010]={},cnt[1010]={},n,m,f,x,y; cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; while(m--){ memset(b+1,0,sizeof(b)); memset(cnt+1,0,sizeof(cnt)); cin>>f>>x>>y; if(f==1) a[x]=y; int e=1; if(f==0){ ... } return 0; }

a[1010]={},👉存储序列

b[1010]={},👉存储出现的数字

cnt[1010]={},👉存储出现的数字个数(跟b数组的下标对应)

n,m,f,x,y;👉n个数,m个操作,f判断操作,x开始下标,y结束下标

memset()函数👉初始化数组

注意:关于memset()函数,我会放到补充部分详细介绍

if(f==1) a[x]=y;👉直接修改数字

int e=1;👉用来记录b数组的最后一位数的下标,e永远指向下一位,因为要空一位存数

if(f==0){..}👉输出最小众数

#include<bits/stdc++.h> using namespace std; int main(){ int a[1010]={},b[1010]={},cnt[1010]={},n,m,f,x,y; cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; while(m--){ memset(b+1,0,sizeof(b)); memset(cnt+1,0,sizeof(cnt)); cin>>f>>x>>y; if(f==1) a[x]=y; int e=1; if(f==0){ for(int i=x;i<=y;i++){ bool check=1; for(int j=1;j<e;j++){ if(b[j]==a[i]){ check=0; cnt[j]++; } } if(check){ b[e]=a[i]; cnt[e++]++; } } ... } return 0; }

for(int i=x;i<=y;i++){...}👉遍历区间内的数字

bool check=1;👉是不是往b数组放不重复的数字(默认放)

for(int j=1;j<e;j++){...}👉跟b数组依次比较

if(b[j]==a[i]){}👉b数组内找到相同的数

check=0;👉不往b数组内放数

cnt[j]++;👉统计数组计数

if(check){...}👉需要往b数组内放数

b[e]=a[i];👉数字存进b数组

#include<bits/stdc++.h> using namespace std; int main(){ int a[1010]={},b[1010]={},cnt[1010]={},n,m,f,x,y; cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; while(m--){ memset(b+1,0,sizeof(b)); memset(cnt+1,0,sizeof(cnt)); cin>>f>>x>>y; if(f==1) a[x]=y; int e=1; if(f==0){ for(int i=x;i<=y;i++){ bool check=1; for(int j=1;j<e;j++){ if(b[j]==a[i]){ check=0; cnt[j]++; } } if(check){ b[e]=a[i]; cnt[e++]++; } } int max_=0,t=0; for(int i=1;i<e;i++){ if(cnt[i]>max_){ max_=cnt[i]; t=b[i]; } if(cnt[i]==max_){ if(b[i]<t) t=b[i]; } } cout<<t<<endl; } } return 0; }

int max_=0,t=0;👉max_存最多的次数,t为具体数字

for(int i=1;i<e;i++){}👉从头到尾遍历

if(cnt[i]>max_){}👉找到最大的数(即出现次数最多的)

if(cnt[i]==max_){}👉找到同样出现次数最多的数

if(b[i]<t) t=b[i];👉取同样数字最小的


补充

memset()函数竞赛完全指南


1. 函数原型与头文件
#include <cstring> // C++ 推荐 // 或 #include <string.h> // C风格 void *memset(void *s, int c, size_t n);

参数说明

  • s:指向要填充的内存块的起始地址

  • c:要填充的值(0~255,但实际以int类型传递)

  • n:要填充的字节数


2. 最常用场景:清零操作
int a[100]; memset(a, 0, sizeof(a)); // 将整个数组每个元素置0 // 等价于 for (int i = 0; i < 100; i++) a[i] = 0;

优势:代码简洁,执行速度极快(通常由硬件指令优化)。


3. 典型应用场景
场景代码示例说明
静态数组清零int arr[1000]; memset(arr, 0, sizeof(arr));将数组所有元素设为0
动态数组清零int* p = new int[100]; memset(p, 0, 100 * sizeof(int));注意:sizeof(p)仅指针大小
结构体清零Student s; memset(&s, 0, sizeof(s));快速初始化所有成员为0/NULL
二维数组清零int g[100][100]; memset(g, 0, sizeof(g));sizeof(g)自动计算总字节数

4. 按字节填充原理与陷阱

memset按字节填充,这是其强大与危险的根源:

  • 清零(0):任何类型都适用,因为全0字节对数值类型就是0,对指针就是NULL

  • 置-1memset(arr, -1, sizeof(arr));也普遍适用,因为-1的补码是0xFF

  • 陷阱不能填充非0xFF的值到多字节类型

int arr[10]; memset(arr, 1, sizeof(arr)); // 危险! // 每个int元素实际是 0x01010101 = 16843009,不是1!

5. 不同类型数据的处理

数值类型

// ✅ 正确:清零或置-1 memset(arr, 0, sizeof(arr)); memset(arr, -1, sizeof(arr)); // ❌ 错误:意图赋其他值 memset(arr, 1, sizeof(arr)); // 实际得到16843009

字符数组

char str[100]; memset(str, 'A', sizeof(str)); // ✅ 正确:所有字符为'A' // 或填充空字符串 memset(str, 0, sizeof(str)); // 全'\0',等价于空字符串

布尔数组

bool flag[100]; memset(flag, 0, sizeof(flag)); // ✅ 全false memset(flag, 1, sizeof(flag)); // ✅ 全true(所有字节为1)

6. 动态内存的特殊处理
// ❌ 错误示范 int* p = new int[100]; memset(p, 0, sizeof(p)); // 只清零了指针本身(4/8字节) // ✅ 正确写法 memset(p, 0, 100 * sizeof(int)); // 计算总字节数 // 或 int n = 100; int* p = new int[n]; memset(p, 0, n * sizeof(int));

7. 与初始化/赋值的区别
方式时机效率适用场景
int a[100] = {0};编译时最快静态数组,只能初始化为0
memset(a, 0, sizeof(a));运行时极快任意时刻,可重复清零
fill(a, a+100, 0);运行时较快可赋任意值,需头文件<algorithm>
for循环赋值运行时较慢灵活,但代码冗余

8. 常见错误
struct Node { int val; vector<int> adj; // ⚠️ 非POD类型 }; Node nodes[100]; memset(nodes, 0, sizeof(nodes)); // ❌ 危险! // 仅将val清零,vector内部状态被破坏,程序可能崩溃

致命问题memset对包含非POD类型(如string,vector)的结构体是未定义行为,会导致程序崩溃。

正确做法

for (int i = 0; i < 100; i++) { nodes[i].val = 0; nodes[i].adj.clear(); }

9. 性能与适用性
  • 性能:在-O2优化下,memset通常比手动循环快数倍

  • 适用性:仅适用于POD类型(Plain Old Data),如基本类型、数组、不含复杂成员的struct

  • 不推荐:含string,vector,map等STL成员的结构体


10. 竞赛最佳实践
#include <bits/stdc++.h> using namespace std; const int MAXN = 1e5 + 5; int arr[MAXN]; bool vis[MAXN]; long long dp[MAXN][2]; int main() { // ✅ 标准清零模板 memset(arr, 0, sizeof(arr)); memset(vis, 0, sizeof(vis)); memset(dp, 0, sizeof(dp)); // 对long long同样有效 // ✅ 多组数据测试时的重置 int T; cin >> T; while (T--) { int n; cin >> n; memset(arr, 0, sizeof(int) * (n + 1)); // 只清零前n+1个 // ... 处理逻辑 } // ✅ 结构体初始化(仅含POD成员) struct Edge { int u, v, w; }; Edge edges[MAXN]; memset(edges, 0, sizeof(edges)); return 0; }

核心要点总结

  1. 万能公式memset(arr, 0, sizeof(arr));永远安全

  2. 仅限-1memset(arr, -1, sizeof(arr));对整数数组有效

  3. 动态数组:必须手动计算字节数n * sizeof(type)

  4. 结构体:仅当所有成员都是POD类型时才可用

  5. 速度:竞赛中清零操作应优先使用memset,比循环快且代码简洁

  6. 陷阱绝不用memset赋1或其他非0xFF值,结果不符合预期

掌握以上用法,可确保在CSP竞赛中安全、高效地使用memset

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/10 3:15:01

Vertex AI创意工作室云部署终极指南:快速上手完整方案

Vertex AI创意工作室云部署终极指南&#xff1a;快速上手完整方案 【免费下载链接】vertex-ai-creative-studio Creative Studio is a Vertex AI generative media example user experience to highlight the use of Imagen and other generative media APIs on Google Cloud. …

作者头像 李华
网站建设 2026/5/9 2:46:22

解决Sanic CLI参数解析异常:告别IndexError困扰

解决Sanic CLI参数解析异常&#xff1a;告别IndexError困扰 【免费下载链接】sanic Accelerate your web app development | Build fast. Run fast. 项目地址: https://gitcode.com/gh_mirrors/sa/sanic Sanic是一个高性能的Python异步Web框架&#xff0c;以其快速的开…

作者头像 李华
网站建设 2026/5/9 0:49:15

N_m3u8DL-CLI-SimpleG终极使用教程:3分钟学会下载M3U8视频

N_m3u8DL-CLI-SimpleG终极使用教程&#xff1a;3分钟学会下载M3U8视频 【免费下载链接】N_m3u8DL-CLI-SimpleG N_m3u8DL-CLIs simple GUI 项目地址: https://gitcode.com/gh_mirrors/nm3/N_m3u8DL-CLI-SimpleG 还在为复杂的命令行操作而头疼&#xff1f;想要轻松下载网络…

作者头像 李华
网站建设 2026/5/9 2:51:29

Qwen3-235B双模式革命:2350亿参数大模型如何改写企业AI应用规则

Qwen3-235B双模式革命&#xff1a;2350亿参数大模型如何改写企业AI应用规则 【免费下载链接】Qwen3-235B-A22B-MLX-6bit 项目地址: https://ai.gitcode.com/hf_mirrors/Qwen/Qwen3-235B-A22B-MLX-6bit 导语&#xff1a;单模型双推理模式&#xff0c;开启大模型效率新纪…

作者头像 李华
网站建设 2026/5/10 14:57:43

Wan2.2-T2V-A14B支持复杂场景描述生成,精准还原创意构想

Wan2.2-T2V-A14B&#xff1a;如何让AI真正“看懂”你的创意&#xff1f; 在影视、广告和短视频内容爆炸式增长的今天&#xff0c;一个现实问题日益凸显&#xff1a;高质量视频的生产速度远远跟不上市场需求。 传统制作流程依赖导演、摄像、剪辑等多角色协作&#xff0c;周期长、…

作者头像 李华
网站建设 2026/5/9 2:30:00

Plus Jakarta Sans 终极使用指南:5步快速掌握现代字体设计

Plus Jakarta Sans 终极使用指南&#xff1a;5步快速掌握现代字体设计 【免费下载链接】PlusJakartaSans Jakarta Sans is a open-source fonts. Designed for Jakarta "City of collaboration" program in 2020. 项目地址: https://gitcode.com/gh_mirrors/pl/Plu…

作者头像 李华