[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 的最大前缀和为 0
mx[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;
posted on 2025-10-10 22:19 符星珞-Astralyn 阅读(6) 评论(0) 收藏 举报
浙公网安备 33010602011771号