POJ - 2010 優先佇列
阿新 • • 發佈:2018-12-07
參考自:https://blog.csdn.net/jhgkjhg_ugtdk77/article/details/38323509
因為是找中位數嘛,所以不必關心這個值的左右到底是誰,只需要知道他可以滿足條件即可;
先按照小牛的分數從小到大排個序;
然後我們需要維護這個小牛的左邊和右邊(n/2)個小牛的最小資助金額;
根據分析,就有了結構體:
struct Cow{
long long val//小牛的分數;
int need//資助金額;
long long lift//表示小牛左邊的最小資助金額;
long long right//表示小牛右邊的最小資助金額;
}a[maxn];
最後只需要從大到小列舉 need+lift+right<=f的就可以啦;
用一個優先佇列存資助額;
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<utility> #include<queue> using namespace std; typedef long long ll; const int inf=0x3f3f3f3f; const double epos=1e-8; const int maxn=1e5+7; struct Cow{ ll val; int need; ll lift; ll right; }a[maxn]; bool cmp(const Cow& x,const Cow& y){ return x.val<y.val; } priority_queue<int>q; int main(){ ll f; int n,c; int t=0; ll val; int need; scanf("%d%d%lld",&n,&c,&f); for(int i=0;i<c;i++){ scanf("%lld%d",&val,&need); if(need<=f){ a[t].val=val; a[t].need=need; ++t; } } sort(a,a+t,cmp); if(n>1){ ll sum=0; //因為要找中位數,所以開頭的n/2個元素肯定是不能選擇的; for(int i=0;i<n/2;i++){ sum+=a[i].need; q.push(a[i].need); } //找左邊的; for(int i=n/2;i<c-n/2;i++){ a[i].lift=sum; int t=a[i].need; int hh=q.top(); if(t<hh){//如果當前的小牛的資助額更小,則更新,方便下一頭牛; sum=sum-hh+t; q.pop(); q.push(t); } } while(!q.empty()) q.pop(); sum=0; //同上; for(int i=c-1;i>=c-n/2;i--){ sum+=a[i].need; q.push(a[i].need); } //找右邊的; for(int i=c-n/2-1;i>=n/2;i--){ a[i].right=sum; int t=a[i].need; int hh=q.top(); if(t<hh){ sum=sum-hh+t; q.pop(); q.push(t); } } } ll ans=-1; for(int i=c-n/2-1;i>=n/2;i--) if(a[i].need+a[i].lift+a[i].right<=f){ ans=a[i].val; break; } printf("%lld\n",ans); return 0; }