题目链接:https://vjudge.net/problem/POJ-2010
题意:给出c个二元组(score,cost),要求选出n(奇数)个,使得选出的score中位数最大,且cost总和<=f,求这个最大中位数。
先对分数降序排序,再预处理从左边和右边开始最小的(n-1)/2的cost的和,l[i]表示从左边开始1到i,r[i]表示从右边开始n到i。具体实现使用优先队列,以l[i]为例,若a[i].cost<q1.top(),则更新l[i]的值为l[i-1]+a[i].cost-q1.top(),并更新q1的堆顶: q1.pop(),q1.push(a[i].cost);否则令l[i]=l[i-1],这样可以实现O(nlogn)预处理。最后枚举中位数,如果l[i-1]+a[i].cost+r[i+1]<=f直接输出a[i].score,循环结束无解就输出-1
1 #include<iostream> 2 #include<queue> 3 #include<algorithm> 4 using namespace std; 5 6 const int maxn=1000+10; 7 struct st{int sc,cost;}a[maxn]; 8 int l[maxn],r[maxn]; 9 int n,c,f,i; 10 priority_queue<int> q1,q2; 11 12 bool cmp(st p,st q){ return p.sc>q.sc;} 13 14 int main(){ 15 std::ios::sync_with_stdio(false); 16 cin>>n>>c>>f; 17 for (i=1;i<=c;i++) cin>>a[i].sc>>a[i].cost; 18 sort(a+1,a+c+1,cmp); 19 for (i=1;i<=(n-1)/2;i++) { 20 l[(n-1)/2]+=a[i].cost; 21 q1.push(a[i].cost); 22 } 23 for (i=(n-1)/2+1;i<=c;i++){ 24 if (a[i].cost<q1.top()){ 25 l[i]=l[i-1]-q1.top()+a[i].cost; 26 q1.pop();q1.push(a[i].cost); 27 } 28 else l[i]=l[i-1]; 29 } 30 for (i=c;i>=c-(n-1)/2+1;i--){ 31 r[c-(n-1)/2+1]+=a[i].cost; 32 q2.push(a[i].cost); 33 } 34 for (i=c-(n-1)/2;i>=1;i--){ 35 if (a[i].cost<q2.top()){ 36 r[i]=r[i+1]-q2.top()+a[i].cost; 37 q2.pop();q2.push(a[i].cost); 38 } 39 else r[i]=r[i+1]; 40 } 41 for (i=(n-1)/2+1;i<=c-(n-1)/2;i++) 42 if (l[i-1]+a[i].cost+r[i+1]<=f){ 43 cout<<a[i].sc<<endl; 44 return 0; 45 } 46 cout<<-1<<endl; 47 return 0; 48 }
应该还有一种二分的做法,待补(咕咕咕)