题目链接
点击打开链接
给你两个栈,push操作是压入,pop是弹出栈顶并输出,merge是将后面的栈合并到前面的栈,并且按压入时间排序。
Solution1 前两个仅仅需要模拟就行了,主要是解决merge,倒过来倒过去,很容易超时,可以定义now为A所属的栈,!now为B所属的栈,那么将元素少的栈合并到元素多的栈里,如果merge A B的时候B的元素多,那么我们把A中的倒入B中,now取反即可。用结构体保存时间。
Solution2 比较简单巧妙的一个做法是引入一个新的栈C,每次合并的时候就把A和B合并到C上,然后把A和B都清空. push还是按正常做,pop注意当遇到要pop的栈为空时,因为题目保证不会对空栈进行pop操作,所以这时应直接改为对C栈进行pop操作. 这样做因为保证每个元素最多只在一次合并中被处理到,pop和push操作当然也是每个元素只做一次,所以总复杂度是O(N)的. 另一种做法是用链表来直接模拟,复杂度也是O(N),但代码量稍大一些.
这里只给出1的代码
#include<stdio.h>
#include<set>
using namespace std;
int nu[100009];
int main(){
int n;int t=1;
while(scanf("%d",&n),n){
printf("Case #%d:\n",t++);
int tim=0;
int now=0;
set<int>s[2];
set<int>::iterator it;
char str[7];
while(n--){
scanf("%s",str);
if(str[1]=='u'){
scanf("%s",str);
int temp;
scanf("%d",&temp);
nu[++tim]=temp;
if(str[0]=='A') s[now].insert(tim);
else s[!now].insert(tim);
}
else if(str[0]=='p'){
scanf("%s",str);
int temp;
if(str[0]=='A')temp=now;
else temp=!now;
it=s[temp].end();it--;
printf("%d\n",nu[*it]);s[temp].erase(it);
}
else{
scanf("%s",str);
scanf("%s",str);
if(str[0]=='B'){
if(s[!now].size() < s[now].size()){
it = s[!now].begin();
while(it != s[!now].end()){
s[now].insert(*it);it ++;
}s[!now].clear();
}
else{
it = s[now].begin();
while(it != s[now].end()){
s[!now].insert(*it);it ++;
}s[now].clear();
now=!now;
}
}
else{
if(s[now].size()<s[!now].size()){
it = s[now].begin();
while(it!=s[now].end()){
s[!now].insert(*it);it++;
}s[now].clear();
}
else{
it = s[!now].begin();
while(it!=s[!now].end()){
s[now].insert(*it);it++;
}s[!now].clear();
now=!now;
}
}
}
}
}
return 0;
}