背包(优先队列/排序)

背包

https://ac.nowcoder.com/acm/problem/17315

Slove:
要求价值的中位数,那首先要对价值进行排序,
m为奇数的情况下
然后我们枚举每个位置,如果该位置是中位数的最大,那么这个位置前面选m/2个的重量加上后面m/2个重量,使他们小于V就说明这个位置可以取得的,只需要维护一个大小为m/2 的堆就行,每次pop掉堆中最大的
m为偶数的时候同理
但是中间需要选择两个位置,数据范围为1e5,n^2肯定不行,所以用nlogn的算法,可以枚举第一个位置,二分第二个位置
代码

#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <cstdio>
#include <bitset>
#include <vector>
#include <iomanip>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define UpMing main
#define re register
#pragma GCC optimize(2)
#define Accept return 0;
#define lowbit(x) ((x)&(-(x)))
#define mst(x, a) memset( x,a,sizeof(x) )
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dep(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef unsigned long long ull;
const int inf =0x3f3f3f3f;
const int maxn=1e5+7;
const ll mod = 1e9+7;
const int N =1e6+3;
inline ll read() {
    ll  x=0;
    bool f=0;
    char ch=getchar();
    while (ch<'0'||'9'<ch)    f|=ch=='-', ch=getchar();
    while ('0'<=ch && ch<='9')
        x=x*10+ch-'0',ch=getchar();
    return f?-x:x;
}
void out(ll x) {
    int stackk[20];
    if(x<0) {
        putchar('-');
        x=-x;
    }
    if(!x) {
        putchar('0');
        return;
    }
    int top=0;
    while(x) stackk[++top]=x%10,x/=10;
    while(top) putchar(stackk[top--]+'0');
}
struct wmy {
    ll v,w;
} a[maxn];
ll v,n,m,sum1[maxn],sum2[maxn];
bool cmp(wmy x,wmy y) {
    return x.v<y.v;
}
priority_queue<ll>q;
int UpMing() {
    v=read(),n=read(),m=read();
    for(int i=1 ; i<=n ; i++) {
        a[i].v=read();
        a[i].w=read();
    }
    sort(a+1,a+1+n,cmp);
    if(m%2) {
        for(int i=1 ; i<=n ; i++) {
            sum1[i]=sum1[i-1]+a[i].w;
            q.push(a[i].w);
            if(q.size()>m/2) sum1[i]-=q.top(),q.pop();
        }
        while(q.size())  q.pop();
        for(int i=n ; i>=1 ; i--) {
            sum2[i]=sum2[i+1]+a[i].w;
            q.push(a[i].w);
            if(q.size()>m/2) sum2[i]-=q.top(),q.pop();
        }
        ll  ans=-inf;
        for(int i=m/2+1; i<=n-m/2; i++)
            if(sum1[i-1]+sum2[i+1]+a[i].w<=v)
                ans=max(ans,a[i].v);
        out(ans);
    } else {
        for(int i=1 ; i<=n ; i++) {
            sum1[i]=sum1[i-1]+a[i].w;
            q.push(a[i].w);
            if(q.size()>m/2-1) sum1[i]-=q.top(),q.pop();
        }
        while(q.size())  q.pop();
        for(int i=n ; i>=1 ; i--) {
            sum2[i]=sum2[i+1]+a[i].w;
            q.push(a[i].w);
            if(q.size()>m/2-1) sum2[i]-=q.top(),q.pop();
        }
    ll ans=-inf;
        for(int i=m/2-1; i<=n-m/2+1; i++) {
            int l=i+1,r=n-m/2+1;
            while(l<=r) {
                ll mid=(l+r)>>1;
                if(sum2[mid+1]+sum1[i-1]+a[i].w+a[mid].w<=v)
                    ans=max(ans,(a[i].v+a[mid].v)>>1),l=mid+1;
                else r=mid-1;
            }
        }
        out(ans);
    }
    Accept;
}
全部评论
%%%
1 回复 分享
发布于 2020-06-12 14:38
禁止自娱自乐
1 回复 分享
发布于 2020-06-12 14:38
orz orz %%%
点赞 回复 分享
发布于 2020-06-12 14:38

相关推荐

求美团让我成为团孝子:帅不帅的不知道 不过我真是拨号机小姐的狗啊
投递TP-LINK等公司10个岗位
点赞 评论 收藏
分享
评论
3
收藏
分享
牛客网
牛客企业服务