CF 1468 C
CF1468C Berpizza
题意
给定以下三个操作:
- 在一条队列中加入整数m
- 输出并删除最先加入的整数的id
- 输出并删除值最大的整数的id
思路
数据大小5e5,队列模拟肯定超了。
但是我们考虑到操作2的特殊性,即每次询问,后一次对操作2的询问必定大于前一次,所以用一个vis数组标记被删除的数,然后从上次操作2的询问开始查找没有被删除的数即可,O(n)。
对于操作3,我们只需要用大根堆模拟即可,每次找值最大的整数并pop,再用vis打上标记,O(nlogn)。
所以总的时间复杂度O(nlogn),满足题目要求。
我们可以通过std::pair来避免构造结构体。
但是pair还有一个细节要考虑,pair优先级是先比第一个元素,再比第二个元素。因此,由于我们在值相同时删除id是从小到大删除,又因为优先队列默认的优先级是从大到小,因此pair的大小顺序需要通过-id这样的操作来维护。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e5 + 5;
int read(){
char ch=getchar();
int x=0,f=1;
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();
return x*f;
}
void solve(){
int id = 1, now = 1, cost, vis[maxn];
priority_queue<pair<int, int> > p;
int q = read();
while (q--)
{
int op = read();
if (op == 1)
{
cost = read();
p.push(make_pair(cost, -id));
id++;
}
else if(op == 2)
{
while (vis[now]) now++;
cout << now << endl;
vis[now] = 1;
}
else if(op == 3)
{
while (vis[-p.top().second])p.pop();
cout << -p.top().second << endl;
vis[-p.top().second] = 1;
}
}
}
int main(){
solve();
}

浙公网安备 33010602011771号