【洛谷】P4952 [USACO04MAR]Financial Aid【DP】【优先队列】

我吐了我是笨比,RE半天才发现原来总数C是1e5,老觉得是n,惯性思维了。

P4952 [USACO04MAR]Financial Aid

思路一下子想出来,但是有很多细节试错了很多次.....

设$t=(n-1)/2$,可以知道题目限定必须取$n$个,那么可能为中位数的区间就是$[t+1,C-t]$。维护$l[i]$和$r[i]$分别表示第$i$头牛牛左边和右边最小的$t$个费用和(不包括自己!!!),那么定义长度始终是$t$的优先队列,维护扫到第$i$个时最小的$t$个费用,在可能是中位数的区间内每次再判断是否需要更新。

注意这里要先更新$l$和$r$,避免把自己更新的算进去!!!(我是笨比)

最后从最后扫一遍,如果扫到了能使$l[i]+r[i]+cow[i].q<=F$的就可以退出了。

查了半天还是没懂stl的运算符重载555,又要验尸自己的blog了。

#include<bits/stdc++.h>

const int N = 100005;

using namespace std;

struct Node {
    int c, q;
} cow[N], co[N];

bool cmp(Node a, Node b) { return a.c < b.c; }

int tmp, l[N], r[N];

int n, C, F;
priority_queue <int> Q;

int main() {
    scanf("%d%d%d", &n, &C, &F);
    for(int i = 1; i <= C; i ++) {
        scanf("%d%d", &cow[i].c, &cow[i].q);
    }
    sort(cow + 1, cow + 1 + C, cmp);
    int sum = 0, t = (n - 1) / 2;
    for(int i = 1; i <= C; i ++) {
        if(i <= t) {
            sum += cow[i].q;
            Q.push(cow[i].q);
        } else {
            l[i] = sum;
            if(cow[i].q < Q.top()) {
                sum = sum - Q.top() + cow[i].q;
                Q.pop();
                Q.push(cow[i].q);
            }
        }
    }
    while(!Q.empty())    Q.pop();
    sum = 0;
    for(int i = C; i >= 1; i --) {
        if(C - i + 1 <= t) {
            sum += cow[i].q;
            Q.push(cow[i].q);
        } else {
            int a = Q.top();
            r[i] = sum;
            if(cow[i].q < Q.top()) {
                sum = sum - Q.top() + cow[i].q;
                Q.pop();
                Q.push(cow[i].q);
            }
        }
    }
    int ans = -1;
    for(int i = C - t; i >= t + 1; i --)
        if(l[i] + r[i] + cow[i].q <= F)    {
            ans = cow[i].c;    break;
        }
    printf("%d", ans);
    return 0;
}

今天观光了pypyzjj和rancyyy的记录,居然都有在写题!!jzdalao从高考完几天就开始,写了好多,最近更新都好频繁!!!危机感upup

posted @ 2020-11-17 21:17  Wans_ovo  阅读(124)  评论(0编辑  收藏  举报