题意
思路
若我们先只看操作1,3,是不是维护一个小顶堆即可;
但现在加上操作2,对所有的数加上一个 x,用堆没法轻易地改元素的值,这里可以类比线段树中的懒标记,每进行一次操作2,我们不是真的把这个 x 加到每一个数上,而是维护一个 lazy 标记,把 x 存起来,当进行操作3时,将 lazy 加到需要输出的数上即可;
但现在还有一个问题,假设当前堆中的序列为 1,2,3,lazy 为 2,现在要往堆中加一个 4,此时改 lazy 标记不应该作用于 4,我们该怎么区分堆中,哪些树有 lazy 标记,哪些没有呢?肯定不能像线段树一样将 lazy 标记加到堆中,在放入新的元素;但可以借助其思想,在线段树中是将线段树中原有的元素都加上 lazy,现在不好操作堆中的元素,但容易操作新加入的数,对原有的元素都加上 lazy,等价于对新元素减去 lazy,我们将新要加入的元素先减去 lazy,再加入堆即可,复杂度;
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
priority_queue<ll,vector<ll>,greater<ll> > q;
ll lazy;
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int n;
ll x,y;
cin>>n;
for(int i=1;i<=n;i++){
cin>>x;
if(x==1){
cin>>y;
y-=lazy;
q.push(y);
}
if(x==2){
cin>>y;
lazy+=y;
}
if(x==3){
ll ans=q.top(); q.pop();
cout<<ans+lazy<<"\n";
}
}
return 0;
}