传送门:http://codeforces.com/contest/681/problem/C
思路:
因为本题的操作是一系列关于堆的操作,而且数据规模也合适,所以我们可以直接用一个堆来模拟这些操作(可用 STL 的 priority _ queue 或 multiset ),然后动态判断当前操作是否合法。当前操作合法时只需要维护堆,且将当前操作加入题目要求我们求的答案序列中即可(可以用数组或 vector 保存)。当前操作不合法时有以下两种情况:
(1)当进行删除最小值操作时操作不合法:说明此时队列为空,需要往答案序列中加入插入任意数的操作。
(2)当进行查询最小值操作时操作不合法:说明要么队列为空,要么最小值与我们维护的堆得最小值不同。前者比较好处理,后者若堆的最小值比查询的值大的话就往队里插入任意数,否则删除最小值直到堆的最小值比查询的值大或变成空堆。
PS:这题主要是细节,不然很容易WA
代码:
#include <bits/stdc++.h>
using namespace std;
#define ff first
#define ss second
#define pb push_back
#define ll __int64
#define ull unsigned long long
#define mod 1000000007
#define mst(ss,b) memset(ss,b,sizeof(ss));
#define pl(x) cout << #x << "= " << x << endl;
const int inf=0x3f3f3f3f;
const int N=1e5+10;
int a[N];
string in[N];
std::vector<string> out;
std::vector<int> b;
priority_queue<int, vector<int>, greater<int> >pq;
int main(){
ios::sync_with_stdio(false);
int n;
cin>>n;
for(int i=1; i<=n; i++){
cin>>in[i];
if(in[i][0]=='r')continue;
else cin>>a[i];
}
for(int i=1; i<=n; i++){
if(in[i][0]=='i'){// 若当前操作是插入操作
pq.push(a[i]);
out.pb("insert");
b.pb(a[i]);
}
else if(in[i][0]=='r'){// 若当前操作是删除操作
if(pq.empty()){// 若堆空则需先让将插入操作加入到答案中
out.pb("insert");
b.pb(0);//随便插入一个
}
else{// 否则对堆执行删除操作
pq.pop();
}
out.pb("removeMin");// 将删除操作加入到答案中
b.pb(0);
}
else{ // 若当前操作是查询操作
if(pq.empty()){ // 若堆空则先维护答案和堆
pq.push(a[i]);
out.pb("insert");
b.pb(a[i]);
}
else if(pq.top()!=a[i]){// 否则若堆顶元素与查询元素不相等
while(!pq.empty() && pq.top()<a[i]){
pq.pop(); // 若堆非空且堆顶元素太小则删除堆顶
out.pb("removeMin");
b.pb(0);
}
if(pq.empty()){// 若上一个循环让堆变空
pq.push(a[i]);
out.pb("insert");
b.pb(a[i]);
}
// 若堆顶元素太大则直接插入待查询元素
else if(pq.top()>a[i]){
pq.push(a[i]);
out.pb("insert");
b.pb(a[i]);
}
}
// 将查询操作加入答案中
out.pb("getMin");
b.pb(a[i]);
}
}
int m=out.size();
cout<<m<<endl;
for(int i=0; i<m; i++){
cout<<out[i];
if(out[i][0]=='r')cout<<endl;
else{
cout<<' '<<b[i]<<endl;
}
}
return 0;
}