第五场周赛(字符串卡常个人Rank赛)——题解

本文解析了Codeforces竞赛的几道题目,包括简单的递归优化、字符串处理、位运算计数等,提供了高效的算法思路和代码实现,如使用树状数组进行区间求和优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本次题目因为比较简单,除了个别题目,其余题目我只写一个思路不再贴代码。

先是Div.2的题解

A题奇怪的优化,把递归函数改成2*fun(...)即可,其实看懂程序也不难,就是求a*2b

B题你会string吗,直接String变量比较大小即可

C题数数,没有卡正常方法,可以直接把数转成二进制找1个数,此时复杂度为O(logN),更快的方法是使用__builtin_popcount函数,复杂度为O(m(m为数二进制中1的个数));

D,E题,看Div.1中本题解释

所有代码都可以10行内写出,所以我不再给出代码;

 

Div.1题解

A题简单代码优化,区间求和,直接再弄一个sum数组即可

B题简单字符串处理,因为只能在字符串尾部加字符,所以我的做法是把每个字符给个序号(既位置)存入容器,再分别做三个操作。

对于1操作,删除存储那个字符的集合即可。

对于2操作,对应集合加上序号即可。

对于3操作,在1操作时候维护一个树状数组即可。

整体时间复杂度为O(QlogN),N为字符个数。但这种写法常数略大,有更优化的思路可以和我探讨一下。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 set<int> dis[26];
 5 vector<pair<int,int>> vis(26,make_pair(0,0));
 6 int q,x,k,tot = 0;
 7 char ch;
 8 int c[100005] = {0};
 9 
10 inline int lowbit(int x){
11     return x&(-x);
12 }
13 
14 int update(int i){
15     while(i <= 100000){
16         c[i] += 1;
17         i += lowbit(i);
18     }
19 }
20 
21 int sum(int i){
22     int res = 0;
23     while(i > 0){
24         res += c[i];
25         i -= lowbit(i);
26     }
27     return res;
28 }
29 
30 int main(){
31     ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
32     freopen("test6.in","r",stdin);
33     freopen("test6.out","w",stdout);
34     int f1 = 0;
35     cin>>q;
36     generate(vis.begin(),vis.end(),[&f1](void)->pair<int,int>{return make_pair(f1++,0);});
37     while(q--){
38         cin>>x;
39         if(x == 1){
40             cin>>k;
41             if(k > 26)
42                 continue;
43             sort(vis.begin(),vis.end(),
44                 [](pair<int,int> a,pair<int,int> b)->bool{
45                     if(a.second == b.second)
46                         return a.first < b.first;
47                     return a.second > b.second;
48                 });
49             vis[k-1].second = 0;
50             for(auto it:dis[vis[k-1].first]){
51                 update(it);
52             }
53             dis[vis[k-1].first].clear();
54         }
55         else if(x == 2){
56             cin>>ch;
57             dis[ch-'a'].insert(++tot);
58             for(auto& a:vis){
59                 if(a.first == ch-'a'){
60                     a.second++;
61                     break;
62                 }
63             }
64         }
65         else if(x == 3){
66             cin>>ch;
67             if(dis[ch-'a'].empty())
68                 cout << -1 << endl;
69             else
70                 cout << *(dis[ch-'a'].begin())-sum(*(dis[ch-'a'].begin())) << endl;
71         }
72     }
73     cerr << clock() << endl;
74     return 0;
75 }
View Code

C题简单信息检索,标记初次出现位置即可

D题高级信息检索,把每个前缀都存入map,此时可以使用unordered_map更快,或者建立Trie树即可。好像还有人写exKMP,也没问题,毕竟100+100数据量。

E题密码破解,马拉车算法裸题。

 

<think>嗯,用户问怎么高效学习算法,这个问题挺见的。首先得了解用户的需求。可能用户是刚开始学编程,或者是想提升算法能力准备面试,比如LeetCode之类的。也可能是在工作中遇到性能问题,需要优化算法。 接下来,用户的身份可能是一个学生,或者刚入行的程序员,或者转行的人士。不同身份可能需要不同的学习路径。比如学生可能有更多时间系统学习,而职场人士可能需要快速应用。 用户可能没有说出来的深层需求,可能是想找到一种不枯燥的学习方法,或者希望有明确的学习路线,避免走弯路。高效学习算法不仅仅是刷题,还需要理解原理和应用场景。 需要从基础开始,强调数据结构的重要性,因为算法数据结构密不可分。然后分阶段学习,比如先基础,再专项突破,再实战。同时要结合正确的学习方法,比如刻意练习、反复复习,以及利用资源如经典教材和在线平台。 还要提醒用户避免见的误区,比如只刷题不总结,或者死记硬背代码。同时,心态调整也很重要,遇到困难时如何坚持下去,保持兴趣。 可能还需要推荐一些资源,比如《算法导论》或者《算法4》,以及在线OJ平台,让用户有实际操作的机会。同时,加入社区讨论,比如参加,可以提升动力和实战能力。 最后,总结高效学习的关键点,强调系统化、刻意练习、多维度结合和长期坚持。这样用户有一个清晰的框架,可以按照步骤逐步提升。</think>学习算法的高效路径需要**系统化学习 + 刻意训练 + 多维度结合**。以下是经过验证的实战方法论,包含**知识体系构建、训练技巧、资源推荐**和**避坑指南**: --- ### 一、**知识体系构建(金字塔模型)** #### 1. **底层基础(30%精力)** - **数据结构必学清单**: ```markdown * 数组/链表 → 理解连续存储链式存储的差异 * 栈/队列 → 掌握FILO和FIFO特性及应用场景 * 哈希表 → 重点理解哈希函数、冲突解决(链地址法/开放寻址法) * 堆 → 优先队列的实现原理(大顶堆/小顶堆) * 树 → 二叉树遍历、AVL树、红黑树(理解旋转平衡) * 图 → 邻接矩阵/邻接表存储、DFS/BFS核心算法 ``` - **算法核心思想**: ```markdown * 分治法(归并排序、快速排序) * 贪心算法(霍夫曼编码、区间调度) * 动态规划(背包问题、最长公共子序列) * 回溯法(N皇后、全排列) * 滑动窗口(字符串子串问题) ``` #### 2. **中层专项突破(50%精力)** - **高频算法题分类训练**: ```markdown * 排序算法 → 掌握快排、堆排序的优化技巧 * 二分查找 → 理解边界条件变种问题 * 双指针 → 链表环检测、三数之和等场景 * 位运算 → 状态压缩、布隆过滤器原理 * 拓扑排序 → 任务调度类问题 * 并查集 → 连通性问题优化 ``` - **复杂度分析训练**: ```python # 通过代码反推时间复杂度 def example(n): sum = 0 for i in range(n): # O(n) for j in range(i): # O(n^2) sum += i*j return sum ``` #### 3. **顶层实战(20%精力)** - **LeetCode刷题策略**: ```markdown * 按标签刷 → 集中突破同类题型(如:链表专题) * 按难度梯度 → 简单题练手速,中等题练思维,难题练建模 * 训练 → 模拟高压环境下的解题能力 ``` --- ### 二、**高效训练技巧** #### 1. **刻意练习法** - **五步刷题法**: ```markdown 1. 独立解题 → 设定15分钟思考时限 2. 对比题解 → 分析最优解自己的差距 3. 手写复现 → 脱离IDE手写代码(面试场景还原) 4. 复杂度推导 → 写出时间/空间复杂度公式 5. 同类迁移 → 寻找相似题目举一反三 ``` - **错题本管理**: ```markdown * 记录:错误原因(边界条件?思路错误?) * 标注:题目类型、相似题链接 * 复盘:每重做错题直至掌握 ``` #### 2. **可视化学习工具** - **推荐工具**: ```markdown * VisuAlgo → 算法执行过程动态演示 * LeetCode动画题解 → 理解复杂问题拆解 * draw.io → 手绘算法流程图 ``` --- ### 三、**资源选择使用** #### 1. **经典教材优先级** | 书籍名称 | 适用阶段 | 核心价值 | |-----------------------|----------------|-----------------------------------| | 《算法图解》 | 入门 | 图形化解释抽象概念 | | 《算法(第4版)》 | 进阶 | Java实现 + 可视化案例 | | 《算法导论》 | 深入研究 | 数学证明复杂度理论 | #### 2. **在线OJ平台对比** ```markdown * LeetCode → 面试高频题库(支持多语言) * Codeforces → 竞级难题训练 * → 中文社区活跃,适合新手 * HackerRank → SQL/正则表达式专项 ``` --- ### 四、**避坑指南** #### 1. **见误区** ```markdown * 盲目刷题 → 刷500道不如精刷100道 * 死记模板 → 忽视问题建模能力培养 * 忽视基础 → 直接学习高级算法导致根基不稳 ``` #### 2. **调试技巧** ```java // 以二叉树遍历为例的调试方法 public void traverse(TreeNode root) { if (root == null) return; System.out.print(root.val + " "); // 打印节点观察执行路径 traverse(root.left); traverse(root.right); } ``` --- ### 五、**实战建议** 1. **项目结合训练**: - 在开发中主动寻找算法优化点(如:缓存淘汰策略 → LRU算法实现) 2. **社区互动**: - 参LeetCode讨论区 → 学习不同解法思路 - 参加编程马拉松(Hackathon) → 提升工程化实现能力 3. **面试突击策略**: ```markdown * 重点突破:Top 100 Liked Questions * 白板编程:使用在线白板工具模拟面试 * 行为面试:准备算法设计案例(如:如何设计推荐系统去重逻辑) ``` --- ### 六、**学习效果检验** ```markdown ✅ 合格标准: - 能在30分钟内解决中等难度题目 - 能推导算法的时间/空间复杂度 - 能向非技术人员解释算法原理 ⏳ 进阶标志: - 对同一问题能给出多种解法(如:DFS/BFS/DP) - 能快速识别题目陷阱(如:整数溢出、空指针) ``` --- **关键总结**:算法学习要遵循「理解 → 记忆 → 应用 → 创新」的递进过程,建议每天保持1-2道高质量题目的精练,配合期性知识体系梳理,通3-6个月可见显著提升。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值