POJ 2010 Moo University - Financial Aid
枚举中位数+优先级队列预处理前x个数选n个最小和
#include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<vector> #include<iostream> #include<algorithm> using namespace std; typedef long long LL; const int maxn=100000+10; int n,c; LL f; struct X { LL s; LL v; } t[maxn]; priority_queue<LL>q; LL dp1[maxn],dp2[maxn]; bool cmp(const X&a,const X&b) { return a.s<b.s; } int main() { scanf("%d%d%lld",&n,&c,&f); for(int i=1; i<=c; i++) scanf("%lld%lld",&t[i].s,&t[i].v); sort(t+1,t+1+c,cmp); LL ans=-1; if(c>=n) { if(n==1) { for(int i=1; i<=c; i++) if(t[i].v<=f) ans=t[i].s; } else { while(!q.empty()) q.pop(); int num=(n-1)/2; for(int i=1; i<=num; i++) dp1[num]=dp1[num]+t[i].v,q.push(t[i].v); for(int i=num+1; i<=c; i++) { if(t[i].v>=q.top()) dp1[i]=dp1[i-1]; else { dp1[i]=dp1[i-1]-(q.top()-t[i].v); q.pop(); q.push(t[i].v); } } while(!q.empty()) q.pop(); for(int i=c; i>=c-num+1; i--) dp2[c-num+1]=dp2[c-num+1]+t[i].v,q.push(t[i].v); for(int i=c-num; i>=1; i--) { if(t[i].v>=q.top()) dp2[i]=dp2[i+1]; else { dp2[i]=dp2[i+1]-(q.top()-t[i].v); q.pop(); q.push(t[i].v); } } for(int i=1; i<=c; i++) { if(i-1<num||c-i<num) continue; if(dp1[i-1]+dp2[i+1]+t[i].v<=f) ans=t[i].s; } } } printf("%lld\n",ans); return 0; }