1. 程式人生 > >HDU 4699 - Editor - [對頂棧]

HDU 4699 - Editor - [對頂棧]

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=4699

Problem Description

Sample Input
8
I 2
I -1
I 1
Q 3
L
D
R
Q 2

Sample Output
2
3

Hint

 

題意:

維護一個整數序列的編輯器,有以下五種操作,操作總數不超過 $10^6$。

$I \: x$:在當前游標位置之後插入一個整數 $x$,插入後游標移動到 $x$ 之後;

$D$:刪除游標前的一個整數;

$L$:游標左移一格;

$R$:游標右移一格;

$Q \: k$:即 $S_i$ 為前 $i$ 個整數的和,查詢 $S_1, S_2, \cdots, S_k$ 中的最大值。

 

題解:

已知 I,D,L,R 這四種操作都是在游標位置處發生,且操作完游標最多移動一個位置,因此可以用對頂棧的做法。

顧名思義,我們以游標為分界,分成左右兩段序列分別由兩個棧 $A,B$ 來維護,兩個棧的棧頂相對。

同時我們可以開一個 $sum$ 陣列來維護棧 $A$ 的字首和,在開一個 $mx[i]$ 陣列來儲存 $sum[1], sum[2], \cdots, sum[i]$ 中的最大值。

 

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10
; const int INF=0x3f3f3f3f; stack<int> A,B; int sum[maxn],mx[maxn]; void update() { int p=A.size(); sum[p]=sum[p-1]+A.top(); mx[p]=max(mx[p-1],sum[p]); } int main() { int q; while(cin>>q) { sum[0]=0; mx[0]=-INF; while(!A.empty()) A.pop();
while(!B.empty()) B.pop(); while(q--) { char op[3]; int k; scanf("%s",op); switch(op[0]) { case 'I': scanf("%d",&k); A.push(k); update(); break; case 'D': A.pop(); break; case 'L': if(A.empty()) break; B.push(A.top()); A.pop(); break; case 'R': if(B.empty()) break; A.push(B.top()); B.pop(); update(); break; case 'Q': scanf("%d",&k); printf("%d\n",mx[k]); break; } } } }