当前位置: 首页 > news >正文

[P2201 数列编辑器 // HDU-4699 Editor] 题解

lougu 看不到,遂写博客

题目描述

小 Z 是一个爱好数学的小学生。最近,他在研究一些关于整数数列的性质。为了方便他的研究,小 Z 希望实现一个叫做 "Open Continuous Lines Processor" 的数列编辑器。

一开始,数列编辑器里没有数字,只有一个光标。这个数列编辑器需要支持五种操作。

  • I x 在当前光标前插入数字 \(x\)
  • D 删除当前光标前的数字。
  • L 光标向前移动一个数字。
  • R 光标向后移动一个数字。
  • Q k 设光标之前的数列是 \(\{a_1,a_2,\cdots,a_n\}\),输出第 \(k\) 位及之前最大的前缀和,保证 \(k\leq n\)

输入格式

第一行包含一个数字 \(N\),表示操作的个数。接下来包含 \(N\) 行,每行包含一条命令。

输出格式

对于每个 Q k 命令,输出一个整数表示这个操作的答案。


  • 对于 \(50\%\) 的数据,\(N\leq 10^3\)
  • 对于 \(80\%\) 的数据,\(N\leq 10^5\)
  • 对于 \(100\%\) 的数据,\(N\leq 10^6\),插入的数字绝对值大小不会超过 \(10^3\)
  • 题目保证不会在数列编辑器为空时进行 D 操作。

解析

本题数据范围只有最后 \(20\%\) 比较难做。

\(80\% \space \text{pts}\) 做法

模拟做法,不用计算每个前缀和,直接用栈维护(用数组也可以模拟),注意指针位置。

...
#define endl '\n'
using namespace std;
using ll = long long;
ll N, x, array[1000005], q=0, ptr=0; // array 为模拟的栈
char opr;ll calpref(ll k){ // 计算前缀和ll prefix_sum = 0, max_sum = -LLONG_MAX;for (int i=1; i<=k; ++i) {prefix_sum += array[i];max_sum = max(max_sum, prefix_sum); // 不全部计算,而是遍历列表,把已经求出来的前缀和和当前最大比较}return max_sum;
}int main(void){ios::sync_with_stdio(0);cout.tie(0);cin.tie(0);memset(array, 0, sizeof array);// 常规卡常cin >> N;while(N--){cin >> opr;if(opr == 'I' || opr == 'Q')cin >> x;if(opr == 'I'){if(ptr != q)for (int i=q; i>ptr; --i) array[i+1] = array[i];// 注意插入元素需要把整体元素向右移动array[++ptr] = x;q++;}else if(opr == 'D'){if(ptr != q)for(int i=ptr; i<q; ++i)array[i] = array[i+1];// 注意删除元素需要把整体元素向左移动ptr--;--q;}else if(opr == 'L'){ // 左移ptr--;}else if(opr == 'R'){ // 右移ptr++;}else if(opr == 'Q'){ll res = calpref(x);cout << res << endl;continue;}}return 0;
}

\(80\space \text{pts}\) 拿到。

\(100\% \space \text{pts}\) 做法

使用对顶栈思想维护,当插入的时候,左栈 \(L\) 增加元素;向左时,左栈 \(L\) 栈顶元素成为右栈 \(R\) 栈顶元素,反之亦然;删除时,删除左栈的栈顶。对于前缀和最大值,另开数组记录。如果左侧栈有改变,修改最大值和前缀和数组。

...
#define endl '\n'
using namespace std;
using ll = long long;
ll N, x, diff[1000005], mx[1000005]; // 前缀和数组和最大前缀和数组
char opr;
stack<ll> L, R; // 左栈和右栈int main(void){memset(diff, 0, sizeof diff);memset(mx, 0, sizeof mx); // 长度为 0 的最大前缀和为 0mx[0] = -LLONG_MAX;cin >> N;for(int i=1; i<=N; ++i){cin >> opr;if(opr == 'I' || opr == 'Q'){cin >> x;if(opr == 'I'){L.push(x); // 插入元素const ll l = L.size();diff[l] = diff[l-1] + L.top(); // 更新前缀和数组mx[l] = max(diff[l], mx[l-1]); // 更新最大前缀和数组}else if(opr == 'Q') cout << mx[x] << endl; // 输出}else{if(opr == 'L' && !L.empty()){R.push(L.top()); // 向左走,R栈顶变为L的栈顶,前缀和数组不变,前缀和最大值数组也不变L.pop();}else if(opr == 'R' && !R.empty()){L.push(R.top()); // 向右走,L栈顶变为R的栈顶R.pop();const ll l = L.size();diff[l] = diff[l-1] + L.top();mx[l] = max(diff[l], mx[l-1]);// 前缀和数组更新,前缀和最大值数组更新}else if(opr == 'D')L.pop(); // 删除元素}}return 0;
}

return 0;

http://www.rkmt.cn/news/18457.html

相关文章:

  • centos网络打流测试 - 指南
  • 实验报告3(使用单链表简单实现图书管理系统)
  • 实验报告1(switch语句,二维数组)
  • 【实现自己的 kafka!】kafka 的关键概念
  • 2024ICPC区域赛香港站
  • 一位印度小哥逆袭成为谷歌数据科学家的心路历程 - 教程
  • Set集合
  • Git 多账号管理
  • P10201 永恒
  • win11 系统如何进行硬盘分区?固态硬盘怎么分区?SSD 固态硬盘分区教程
  • JavaScriptDay1
  • 3 ABC411 C ~ E题解
  • 9 ABC408 D~F 题解
  • 8 ABC425 G 题解
  • 学习ReAct并使用langgraph实现一个简单的ReAct AI Agent!!
  • 23种设计模式之【策略模式】-核心原理与 Java 实践 - 详解
  • RMQ与LCA学习笔记
  • mamba-硬件感知算法
  • gitee和github如何修改仓库名并且保持与原远程仓库的连接?(手把手教学) - 实践
  • 第十一篇
  • 如何在 Spring Boot 应用中配置多个 Spring AI 的 LLM 客户端
  • [Git] 放弃暂存区的修改
  • 前端里面transform和transition 属性的区别
  • 【MAC环境】安装多个 JDK - 指南
  • 第一个博客
  • k8s 主节点重启后 从节点 get 异常 - 教程
  • 训练笔记:博弈杂题
  • PyTorch 神经网络工具箱完全指南 - 详解
  • 2025表面瑕疵检测厂家TOP5推荐:表面瑕疵检测,薄膜瑕疵检测,瑕疵检测设备,瑕疵在线检测,铝箔瑕疵在线检测,外观瑕疵检测机,薄膜瑕疵检测仪,陶瓷膜瑕疵检测各种类型检测,精准高效的质量守护
  • 深入解析:如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘tokenizers’ 问题