题目链接:点击打开链接
题目大意:给定T个操作,A栈和B栈,操作包含三种,一种是push,即向A栈或B栈中加入一个新元素,一种是pop即输出A栈或B栈的栈顶元素,最后一个是merge,即合并两个栈,并保留第一个栈清空第二个栈(即如果输入merge B A为保留B,清空A)。
题目解析:比赛的时候自己想到去模拟一下,时间复杂度肯定没问题,就是调试可能会耗点时间,于是让队友现行上模板用左式堆过掉了,比赛之后刷一刷其他人的博客发现三个优先队列也是可以的,校内的另一支队伍用双向链表也过了,不过道理和优先队列是差不多的。直接给代码吧,题意很清晰,没啥难点。
先上一个我赛后自己写的一个模拟吧,就把所有push都记录下来,设立一个A、B标记,用于标记A栈pop的位置和B栈pop的位置,C记录一下合并的时候从哪个位置开始是都属于某一个栈的,D是记录是哪一个栈。
//模拟法
#include <algorithm>
#include <iostream>
#include <numeric>
#include <cstring>
#include <iomanip>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
#define LL __int64
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define Pair pair<int,int>
const int INF = 0x3f3f3f3f;
using namespace std;
struct node{
int choose;
bool is_pop;
int val;
}arr[100005];
int T,x,tot;
char op[15],chos[5];
int main(){
int cas = 1,A,B,C,D;
while(~scanf("%d",&T) && T){
printf("Case #%d:\n",cas++);
tot = A = B = D = 0;
C = -1;
for(int l=0;l<T;l++){
scanf("%s",op);
if(op[1] == 'u'){
scanf("%s %d",chos,&x);
arr[tot].is_pop = false;
arr[tot].choose = (chos[0]=='A')?1:2;
arr[tot].val = x;
if(chos[0] == 'A') //记录A、B栈的栈顶
A = tot;
else
B = tot;
tot += 1;
}
else if(op[1] == 'o'){
scanf("%s",chos);
if(chos[0] == 'A'){
printf("%d\n",arr[A].val);//输出栈顶,并且寻找下一个栈顶
arr[A].is_pop = true;
for(int i=A;i>=0;i--){
if(C == -1){ //如果之前合并过
if(arr[i].choose == 1 && arr[i].is_pop == false){
A = i;
break;
}
}
else{
if(i <= C){
if(D == 1){
if(arr[i].is_pop == false){
A = i;
break;
}
}
}
else{
if(arr[i].choose == 1 && arr[i].is_pop == false){
A = i;
break;
}
}
}
}
}
else{
printf("%d\n",arr[B].val);
arr[B].is_pop = true;
for(int i=B;i>=0;i--){
if(C == -1){
if(arr[i].choose == 2 && arr[i].is_pop == false){
B = i;
break;
}
}
else{
if(i <= C){
if(D == 2){
if(arr[i].is_pop == false){
B = i;
break;
}
}
}
else{
if(arr[i].choose == 2 && arr[i].is_pop == false){
B = i;
break;
}
}
}
}
}
}
else if(op[1] == 'e'){
scanf("%s %s",op,chos);
if(op[0] == 'A'){ //合并之后要重新计算栈顶
D = 1;
for(int i=tot-1;i>=0;i--){
if(arr[i].is_pop == false){
A = i;
break;
}
}
}
else{
D = 2;
for(int i=tot-1;i>=0;i--){
if(arr[i].is_pop == false){
B = i;
break;
}
}
}
C = tot - 1;
}
}
}
return 0;
}
//左式堆
#include <algorithm>
#include <iostream>
#include <numeric>
#include <cstring>
#include <iomanip>
#include <string>
#include <vector>
#include <cstdio>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
using namespace std;
template <typename Comparable>
class LeftistHeap
{
public:
LeftistHeap():root(NULL)
{}
LeftistHeap(const LeftistHeap &rhs)
{
*this = rhs;
}
~LeftistHeap()
{
clear();
}
void push(const Comparable &x)
{
root = merge(new LeftistNode(x), root);
}
bool empty() const
{
return root == NULL;
}
const Comparable& top() const
{
return root->element;
}
void pop()
{
if(empty())
return;
LeftistNode* oldroot = root;
root = merge(root->left, root->right);
delete oldroot;
}
void pop(Comparable &minItem)
{
minItem = top();
pop();
}
void clear()
{
reclaimMemory(root);
root = NULL;
}
void merge(LeftistHeap &rhs)
{
if(this == &rhs)
return;
root = merge(root, rhs.root);
rhs.root = NULL;
}
const LeftistHeap& operator=(const LeftistHeap &rhs)
{
if(this != &rhs)
{
clear();
root = clone(rhs.root);
}
return *this;
}
private:
struct LeftistNode
{
Comparable element;
LeftistNode *left;
LeftistNode *right;
int npl;
LeftistNode(const Comparable &e, LeftistNode *l = NULL,
LeftistNode *r = NULL, int n = 0)
:element(e), left(l), right(r), npl(n)
{}
};
LeftistNode *root;
LeftistNode* merge(LeftistNode *h1, LeftistNode *h2)
{
if(h1 == NULL)
return h2;
if(h2 == NULL)
return h1;
if(h1->element < h2->element)
return merge1(h1, h2);
else
return merge1(h2, h1);
}
LeftistNode* merge1(LeftistNode *h1, LeftistNode *h2)
{
if(h1->left == NULL)
h1->left = h2;
else
{
h1->right = merge(h1->right, h2);
if(h1->left->npl < h1->right->npl)
swapChildren(h1);
h1->npl = h1->right->npl + 1;
}
return h1;
}
void swapChildren(LeftistNode *t)
{
LeftistNode *tmp = t->left;
t->left = t->right;
t->right = tmp;
}
void reclaimMemory(LeftistNode *t)
{
if(t != NULL)
{
reclaimMemory(t->left);
reclaimMemory(t->right);
delete t;
}
}
LeftistNode *clone(LeftistNode *t) const
{
if(t == NULL)
return NULL;
else
return new LeftistNode(t->element, clone(t->left), clone(t->right));
}
};
struct info
{
int t,x;
info(){}
info(int a,int b):t(a),x(b){}
bool operator < (const info &a)const
{
return t > a.t;
}
};
LeftistHeap<info> A,B;
int main()
{
int n;
int cas = 0;
while(~scanf("%d",&n) && n)
{
A.clear();
B.clear();
printf("Case #%d:\n",++cas);
int x;
char op[10];
char stk[10],stk2[10];
for(int i = 0 ; i < n ; i++)
{
scanf("%s",op);
if(op[1] == 'u') //push
{
scanf("%s %d",stk,&x);
if(stk[0] == 'A')
A.push(info(i,x));
else
B.push(info(i,x));
}
else if(op[1] == 'o') //pop
{
scanf("%s",stk);
if(stk[0] == 'A')
{
printf("%d\n",A.top().x);
A.pop();
}
else
{
printf("%d\n",B.top().x);
B.pop();
}
}
else //merge
{
scanf("%s %s",stk,stk2);
if(stk[0] == 'A') //B to A
{
A.merge(B);
}
else //A to B
{
B.merge(A);
}
}
}
}
return 0;
}
<span style="font-family: Arial, Helvetica, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);">//优先队列</span>
#include <algorithm>
#include <iostream>
#include <numeric>
#include <cstring>
#include <iomanip>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
#define LL __int64
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define Pair pair<int,int>
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> pii;
priority_queue<pii> com;
priority_queue<pii> a;
priority_queue<pii> b;
int main(int argc, char const *argv[])
{
//IN;
int n; int ca = 1;
while(scanf("%d", &n) != EOF && n)
{
printf("Case #%d:\n", ca++);
while(!a.empty()) a.pop();
while(!b.empty()) b.pop();
while(!com.empty()) com.pop();
int time_cnt = 0;
while(n--) {
char op[10]; char aim;
scanf("%s %c", op,&aim);
if(op[1] == 'u') {
int x; scanf("%d", &x);
if(aim == 'A') {
a.push(make_pair(time_cnt++, x));
} else {
b.push(make_pair(time_cnt++, x));
}
}
else if(op[1] == 'o') {
if(aim == 'A') {
if(!a.empty()) {
pii x = a.top(); a.pop();
printf("%d\n", x.second);
} else {
pii x = com.top(); com.pop();
printf("%d\n", x.second);
}
} else {
if(!b.empty()) {
pii x = b.top(); b.pop();
printf("%d\n", x.second);
} else {
pii x = com.top(); com.pop();
printf("%d\n", x.second);
}
}
}
else {
char tmp[10]; gets(tmp);
while(!a.empty()) {
pii x = a.top();
a.pop();
com.push(x);
}
while(!b.empty()) {
pii x = b.top();
b.pop();
com.push(x);
}
}
}
}
return 0;
}

本文介绍了一道关于栈操作模拟的问题,包括push、pop和merge操作,并提供了三种不同的解决方案:模拟法、使用左式堆和优先队列。通过这些方法展示了如何高效地处理栈的操作,特别适用于算法竞赛。
1万+

被折叠的 条评论
为什么被折叠?



