11113: 【原1113】二哥的奖学金
题目
题目描述
author: Cheng Chen 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1113
Description
二哥发表论文后,有一个神秘人物要为二哥的学校发奖学金。二哥的学校有C名学生,要从中挑出N个。这个神秘人物的爱好比较奇特,他希望得到奖学金的同学的成绩的中位数尽量大。但同时,他们的奖学金总额不能超过F。
Input Format
第一行整数是N、C和F。N一定是奇数,N <= C,0 <=F<= 2000000000,N<=100000,C<=20000。 接下来的C行,每行描述一名学生的成绩和奖学金。0<=成绩<=2000000000;0 <=奖学金<=100000。
Output Format
满足条件的最大中位数。如果无解,输出-1。
Sample Input
3 5 70
30 25
50 21
20 20
5 18
35 30
Sample Output
35
FineArtz's solution
/* 二哥的奖学金 */
#include <iostream>
#include <algorithm>
using namespace std;
const int INF = 2000000005;
class Heap{
private:
int a[200005] = {0};
int heapsize = 0;
void swap(int x, int y){
int t = a[x];
a[x] = a[y];
a[y] = t;
}
void siftup(int i){
while (i != 1){
if (a[i] > a[i / 2]){
swap(i, i / 2);
i /= 2;
}
else
break;
}
}
void siftdown(){
int i = 2;
while (i <= heapsize){
if (i + 1 <= heapsize && a[i] < a[i + 1])
++i;
if (a[i / 2] < a[i]){
swap(i, i / 2);
i *= 2;
}
else
break;
}
}
public:
void insert(int x){
a[++heapsize] = x;
siftup(heapsize);
}
void remove(){
swap(1, heapsize);
--heapsize;
siftdown();
}
int getMax(){
return a[1];
}
void removeAndInsert(int x){
a[1] = x;
siftdown();
}
};
pair<int, int> a[200005];
int sum1[200005] = {0}, sum2[200005] = {0};
int n, c, f;
Heap heap1, heap2;
void qsort(int l, int h){
if (l >= h)
return;
int i = l, j = h;
pair<int, int> key = a[l];
while (i < j){
while (i < j && a[j] > key)
--j;
a[i] = a[j];
while (i < j && a[i] < key)
++i;
a[j] = a[i];
}
a[i] = key;
qsort(l, i - 1);
qsort(i + 1, h);
}
int main(){
cin >> n >> c >> f;
for (int i = 1; i <= c; ++i){
cin >> a[i].first >> a[i].second;
}
sort(a + 1, a + c + 1);
// for (int i = 1; i <= c; ++i)
// cout << a[i].first << ' ' << a[i].second << endl;
for (int i = 1; i <= n / 2; ++i){
sum1[n / 2] += a[i].second;
heap1.insert(a[i].second);
}
for (int i = n / 2 + 1; i <= c; ++i){
int t = a[i].second;
if (t > heap1.getMax())
sum1[i] = sum1[i - 1];
else{
sum1[i] = sum1[i - 1] - heap1.getMax() + t;
heap1.remove();
heap1.insert(t);
}
}
for (int i = c; i >= c - n / 2 + 1; --i){
sum2[c - n / 2 + 1] += a[i].second;
heap2.insert(a[i].second);
}
for (int i = c - n / 2; i >= 1; --i){
int t = a[i].second;
if (t > heap2.getMax())
sum2[i] = sum2[i + 1];
else{
sum2[i] = sum2[i + 1] - heap2.getMax() + t;
heap2.remove();
heap2.insert(t);
}
}
int ans = -1;
for (int i = n / 2 + 1; i <= c - n / 2; ++i){
int t = sum1[i - 1] + sum2[i + 1] + a[i].second;
if (t <= f && ans < a[i].first)
ans = a[i].first;
}
cout << ans << endl;
return 0;
}
yyong119's solution
#include <cstdio>
#include <algorithm>
#include <iostream>
#define MAX_C 100010
#define RG register
using namespace std;
struct Node {
int grd, sch;
} a[MAX_C];
int n, c, f, half;
int sum_left[MAX_C], sum_right[MAX_C], max_heap[MAX_C];
inline int read() {
char ch = getchar(); int flag = 1, res = 0;
while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
if (ch == '-') flag = -1, ch = getchar();
while (ch >= '0' && ch <= '9') res = res * 10 + ch - '0', ch = getchar();
return res * flag;
}
inline bool cmp_grd(const Node& a, const Node& b) {
return a.grd < b.grd;
}
inline bool cmp_sch(const Node& a, const Node& b) {
return a.sch < b.sch;
}
int main() {
n = read(); c = read(); f = read();
half = n >> 1;// numbers that two side of center number need
for (RG int i = 0; i < c; ++i)
a[i].grd = read(), a[i].sch = read();
sort(a, a + c, cmp_grd);
// calc minimum sum of the left part
for (RG int i = 0; i < half; ++i) {
max_heap[i] = a[i].sch;
sum_left[half - 1] += a[i].sch;
}
make_heap(max_heap, max_heap + half, less<int>());
for (RG int i = half; i < c; ++i) {
sum_left[i] = sum_left[i - 1];
if (a[i].sch < max_heap[0]) {
sum_left[i] -= max_heap[0];
sum_left[i] += a[i].sch;
pop_heap(max_heap, max_heap + half, less<int>());
max_heap[half - 1] = a[i].sch;
push_heap(max_heap, max_heap + half, less<int>());
}
}
// calc minimum sum of the right part
for (RG int i = c - 1; i >= c - half; --i) {
max_heap[c - i - 1] = a[i].sch;
sum_right[c - half] += a[i].sch;
}
make_heap(max_heap, max_heap + half, less<int>());
for (RG int i = c - half - 1; i >= 0; --i) {
sum_right[i] = sum_right[i + 1];
if (a[i].sch < max_heap[0]) {
sum_right[i] -= max_heap[0];
sum_right[i] += a[i].sch;
pop_heap(max_heap, max_heap + half, less<int>());
max_heap[half - 1] = a[i].sch;
push_heap(max_heap, max_heap + half, less<int>());
}
}
// enumerate each center number
for (RG int i = c - half - 1; i >= half; --i)
if (sum_left[i - 1] + sum_right[i + 1] + a[i].sch <= f) {
printf("%d\n", a[i].grd);
return 0;
}
printf("-1\n");
return 0;
}