题解:AT_abc388_e [ABC388E] Simultaneous Kagamimochi
Kotobuki_Tsumugi · · 题解
有点小题大做的感觉,本题我们使用反悔贪心解决。
反悔贪心的一般策略大概可以概括为:能对答案产生贡献的方案就直接选下来,否则,我们找一下前面选过的最不优的方案进行更换。
那本题我们也可以这样。不妨开两个优先队列,一个
先排序。然后往后面扫。设当前扫到的是
- 如果
q2 中的最小数top 可以与之搭配,即满足top\times 2\le now ,那么搭配,将二元组(top,now) 存进q1 。答案加一。 - 若不能,取出
q1 的队头(x,y) ,改为(x,now) 。然后把y 弹入q2 。这一步的操作可以理解为,把较小的y 取出来,以便后面和其他的数配对。 - 如果上述两种均不满足,那就直接将
now 弹入q2 。
那么完成了。时间复杂度是
请注意,由于优先队列存放 pair 时以第一个数为关键字,所以我们把二元组对调即可。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6+10;
int a[N],n,ans;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i = 1;i<=n;i++)
cin>>a[i];
sort(a+1,a+n+1);
priority_queue<pair<int,int>,vector<pair<int,int> > ,greater<pair<int,int> > > q1;
priority_queue<int,vector<int>,greater<int> > q2;
for(int i = 1;i<=n;i++){
if(!q2.empty() && q2.top()*2 <= a[i]){
ans++;
q1.push(make_pair(a[i],q2.top()));
q2.pop();
}
else if(!q1.empty() && q1.top().first < a[i]){
pair<int,int> f = q1.top();
q1.pop();
q2.push(f.first);
q1.push(make_pair(a[i],f.second));
}
else q2.push(a[i]);
}
cout<<ans<<endl;
return 0;
}