记录一个菜逼的成长。。
比较简单巧妙的一个做法是引入一个新的栈C,每次合并的时候就把A和B合并到C上,然后把A和B都清空. push还是按正常做,pop注意当遇到要pop的栈为空时,因为题目保证不会对空栈进行pop操作,所以这时应直接改为对C栈进行pop操作. 这样做因为保证每个元素最多只在一次合并中被处理到,pop和push操作当然也是每个元素只做一次,所以总复杂度是O(N)的. 另一种做法是用链表来直接模拟,复杂度也是O(N),但代码量稍大一些.
PS:还是水。。训练的时候一直吃T 。。Orz.
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <list>
#include <deque>
#include <cctype>
#include <bitset>
#include <cmath>
using namespace std;
#define ALL(v) (v).begin(),(v).end()
#define cl(a) memset(a,0,sizeof(a))
#define fin freopen("D://in.txt","r",stdin)
#define fout freopen("D://out.txt","w",stdout)
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef vector<PII> VPII;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 100000 + 10;
PII a[maxn],b[maxn],c[maxn];
char ope[10],str[5],s[5];
void _merge(PII *a,int n,PII *b,int m,PII *c,int len)
{
int i = 0, j = 0,k = len;
while(i < n && j < m){
if(a[i].second < b[j].second){
c[k++] = a[i++];
}
else c[k++] = b[j++];
}
while(i < n)c[k++] = a[i++];
while(j < m)c[k++] = b[j++];
}
int main()
{
//fin;
//fout;
int n,cas = 1;
while(~scanf("%d",&n),n){
int cnt = 0;
int inda = 0,indb = 0,indc = 0;
printf("Case #%d:\n",cas++);
for( int x,i = 0; i < n; i++ ){
scanf("%s%s",ope,str);
if(ope[1] == 'u'){
scanf("%d",&x);
if(str[0] == 'A')
a[inda++] = PII(x,cnt++);
else
b[indb++] = PII(x,cnt++);
}
else if(ope[1] == 'o'){
if(str[0] == 'A'){
if(inda)printf("%d\n",a[--inda].first);
else printf("%d\n",c[--indc].first);
}
else {
if(indb)printf("%d\n",b[--indb].first);
else printf("%d\n",c[--indc].first);
}
}
else{
scanf("%s",s);
_merge(a,inda,b,indb,c,indc);//直接往c的后面加,因为前面的序号一定比现在要合并的小,并不需要重新全部排过;
indc += inda + indb;
inda = indb = 0;
}
}
}
return 0;
}