POJ 2010 Moo University

枚举中位数+优先级队列预处理前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
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/zufezzt/p/5352195.html