题目链接:
https://vjudge.net/problem/POJ-2010
题目大意:
奶牛大学:奶大招生,从C头奶牛中招收N头。它们分别得分score_i,需要资助学费aid_i。希望新生所需资助不超过F,同时得分中位数最高。求此中位数。
思路:
按照分数排序,依次枚举中位数,然后用优先队列维护该头牛作为中位数的时候左边的money最小值和右边money的最小值,最后直接找出符合条件的最大的socre就可以了
1 #include<iostream> 2 #include<vector> 3 #include<queue> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdio> 7 #include<set> 8 #include<map> 9 #include<cmath> 10 using namespace std; 11 typedef pair<int, int> Pair; 12 typedef long long ll; 13 const int INF = 0x3f3f3f3f; 14 ll T, n, m, d; 15 const int maxn = 1e5 + 10; 16 struct cow 17 { 18 ll score, money, left, right; 19 bool operator <(const cow & a)const 20 { 21 return score < a.score; 22 } 23 }; 24 cow a[maxn]; 25 int main() 26 { 27 priority_queue<ll>q; 28 ll tot, sum = 0; 29 cin >> n >> m >> tot; 30 for(int i = 1; i <= m; i++)scanf("%d%d", &a[i].score, &a[i].money); 31 sort(a + 1, a + m + 1); 32 for(int i = 1; i <= n / 2; i++)//将前n/2头牛的money加入队列 33 { 34 sum += a[i].money; 35 q.push(a[i].money); 36 } 37 for(int i = n / 2 + 1; i <= m - n / 2; i++)//枚举中位数,用优先队列保持左边最小 38 { 39 a[i].left = sum; 40 sum += a[i].money; 41 q.push(a[i].money); 42 sum -= q.top(); 43 q.pop(); 44 } 45 while(!q.empty())q.pop(); 46 sum = 0; 47 for(int i = m; i > m - n / 2; i--)//将后n/2头牛的money加入队列 48 { 49 sum += a[i].money; 50 q.push(a[i].money); 51 } 52 for(int i = m - n / 2; i > n / 2; i--)//枚举中位数,用优先队列保持右边最小 53 { 54 a[i].right = sum; 55 sum += a[i].money; 56 q.push(a[i].money); 57 sum -= q.top(); 58 q.pop(); 59 } 60 ll ans = -1; 61 //for(int i = 1; i <= m; i++)cout<<a[i].score<<" "<<a[i].money<<" "<<a[i].left<<" "<<a[i].right<<endl; 62 for(int i = m - n / 2; i > n / 2; i--) 63 { 64 if(a[i].left + a[i].right + a[i].money <= tot) 65 { 66 ans = a[i].score; 67 break; 68 } 69 } 70 cout<<ans<<endl; 71 return 0; 72 }