zoukankan      html  css  js  c++  java
  • NC17315 背包(优先队列+二分)

    这题奇数部分比较容易想到,用优先队列维护每个位置前能否取到指定个数,这样枚举每个位置座位中位数即可

    对于偶数,由于两个数位置不确定,并且不能枚举两个,因此还是考虑要维护一个

    这样就需要一个log复杂度以内的算法找到每个对应的最优解,常见的就是二分算法

    我们观察题目性质,果然符合单调性,因为对于左边定好的数,第二个肯定越右越好,并且我们知道越右满足条件的难度越大,因此考虑二分找到最右点

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    const int N=2e5+10;
    const int inf=1e9;
    const int mod=1e9+7;
    ll v,n,m;
    ll pre[N],suf[N];
    priority_queue<ll> q;
    struct node{
        ll a,b;
    }s[N];
    bool cmp(node a,node b){
        return a.a<b.a;
    }
    int main(){
        ios::sync_with_stdio(false);
        int i;
        ll sum=0;
        cin>>v>>n>>m;
        for(i=1;i<=n;i++){
            cin>>s[i].a>>s[i].b;
        }
        sort(s+1,s+1+n,cmp);
        for(i=1;i<=n;i++){
            pre[i]=pre[i-1]+s[i].b;
            q.push(s[i].b);
            while(q.size()>(m-1)/2){
                pre[i]-=q.top();
                q.pop();
            }
        }
        while(q.size())
            q.pop();
        for(i=n;i>=1;i--){
            suf[i]=suf[i+1]+s[i].b;
            q.push(s[i].b);
            if(q.size()>(m-1)/2){
                suf[i]-=q.top();
                q.pop();
            }
        }
        ll ans=0;
        if(m%2){
            for(i=n-(m-1)/2;i>(m-1)/2;i--){
                if(s[i].b+pre[i-1]+suf[i+1]<=v){
                    ans=max(ans,s[i].a);
                }
            }
            cout<<ans<<endl;
        }
        else{
            for(i=(m-1)/2+1;i<n-(m-1)/2;i++){
                int l=i+1,r=n-(m-1)/2;
                int tmp=v-s[i].b-pre[i-1];
                while(l<=r){
                    int mid=l+r>>1;
                    if(suf[mid+1]+s[mid].b<=tmp){
                        ans=max(ans,(s[i].a+s[mid].a)/2);
                        l=mid+1;
                    }
                    else{
                        r=mid-1;
                    }
                }
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    linux下删除乱码文件
    linux修改网卡延时、带宽、丢包等
    连接远程系统里的vbox虚拟机
    Linux路由功能
    关于C语言的取整函数
    新博客
    NEU1217之神风堂最少人数 自己在精度上吃了苦头
    sprintf sscanf自己应该会的小点
    【转】妙解亲和数
    redeclared as different kind of symbol
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/14394405.html
Copyright © 2011-2022 走看看