【洛谷】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