Kotobuki_Tsumugi
2025-01-12 10:51:35
有点小题大做的感觉,本题我们使用反悔贪心解决。
反悔贪心的一般策略大概可以概括为:能对答案产生贡献的方案就直接选下来,否则,我们找一下前面选过的最不优的方案进行更换。
那本题我们也可以这样。不妨开两个优先队列,一个
先排序。然后往后面扫。设当前扫到的是
那么完成了。时间复杂度是
请注意,由于优先队列存放 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;
}