Codeforces Round #420 (Div. 2)

题目链接:http://codeforces.com/contest/821/problem/C

题意:起初有一个栈,给定2*n个命令,其中n个命令是往栈加入元素,另外n个命令是从栈中取出元素。你可以在任何操作之前重新排列目前栈内的元素,现在要求对于取出的元素序列为1~n。问你至少要重新排列栈内的元素几次。 题目保证出栈时下一个要求出栈的元素一定在栈内。

思路:

维护一个栈和优先队列

对于出栈操作,存在3中情况:

1,栈顶元素刚好是下一个要出栈的元素,直接出栈即可。

2,栈为空,队列头一定是下一个要出栈的元素,直接对头出队即可。

3,栈不为空,栈顶非下一个要出栈的元素,并且队头也非下一个要出栈的元素,将栈内元素全部加入队列中,清空栈,并且重排(由于优先队列就是一个堆,直接加入即可满足重排)。 重排后队头一定是下一个要出栈的元素。

由于题目保证出栈时下一个要求出栈的元素一定在栈内。所以只有上面3中情况。

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<time.h>
#include<stack>
#include<cmath>
using namespace std;
typedef long long int LL;
const LL INF = 9223372036854775807;
const int MAXN = 3e5 + 24;
stack<int>st;
priority_queue<int>buff;
int main(){
//#ifdef kirito
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//#endif
//    int start = clock();
    int n;
    while (~scanf("%d", &n)){
        int nextNum = 1, ans = 0;
        while (!st.empty()){ st.pop(); }
        while (!buff.empty()){ buff.pop(); }
        for (int i = 0; i < n * 2; i++){
            char tpe[10]; int val;
            scanf("%s", tpe);
            if (tpe[0] == 'a'){
                scanf("%d", &val);
                st.push(val);
            }
            else{
                if (st.empty()){
                    buff.pop();
                }
                else if (!st.empty() && st.top() == nextNum){
                    st.pop();
                }
                else{
                    ans++;
                    while (!st.empty()){
                        buff.push(st.top());
                        st.pop(); 
                    }
                    buff.pop();
                }
                nextNum++;
            }
        }
        printf("%d
", ans);
    }
//#ifdef LOCAL_TIME
//    cout << "[Finished in " << clock() - start << " ms]" << endl;
//#endif
    return 0;
}
原文地址:https://www.cnblogs.com/kirito520/p/7094884.html