【HDU5818】Joint Stacks(模拟)

记录一个菜逼的成长。。

比较简单巧妙的一个做法是引入一个新的栈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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值