zoukankan      html  css  js  c++  java
  • [bzoj5343][Ctsc2018]混合果汁——二分答案+主席树

    题目描述:

    小 R 热衷于做黑暗料理,尤其是混合果汁。

    商店里有 nn 种果汁,编号为 0,1,,n10,1,cdots,n-1ii 号果汁的美味度是 did_i,每升价格为 pip_i。小 R 在制作混合果汁时,还有一些特殊的规定,即在一瓶混合果汁中,ii 号果汁最多只能添加 lil_i 升。

    现在有 mm 个小朋友过来找小 R 要混合果汁喝,他们都希望小 R 用商店里的果汁制作成一瓶混合果汁。其中,第 jj 个小朋友希望他得到的混合果汁总价格不大于 gjg_j,体积不小于 LjL_j。在上述这些限制条件下,小朋友们还希望混合果汁的美味度尽可能地高,一瓶混合果汁的美味度等于所有参与混合的果汁的美味度的最小值。请你计算每个小朋友能喝到的最美味的混合果汁的美味度。

    思路:

    答案很明显具有单调性,考虑对于每一个询问二分答案。
    二分一个最小值(d_i)后把所有美味值(geq d_i)的果汁按照价格从小到大排序,然后贪心地一直选择,直到sum(geq L_i)为之。
    不难发现排序的过程复杂度较高,每一次是先按照(d_i)排序之后再按照(p_i)排序,于是我们可以直接按照(d_i)的顺序以(p_i)为下标构建一颗主席树,每一次直接在主席树上面二分查找就好了。

    #include<bits/stdc++.h>
     
    #define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
    #define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
    #define MREP(i,x) for(int i=beg[x],v;v=to[i],i;i=las[i])
    #define debug(x) cout<<#x<<"="<<x<<endl
    #define fi first
    #define se second
    #define mk make_pair
    #define pb push_back
    typedef long long ll;
     
    using namespace std;
     
    void File(){
        freopen("bzoj5343.in","r",stdin);
        freopen("bzoj5343.out","w",stdout);
    }
     
    template<typename T>void read(T &_){
        T __=0,mul=1; char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')mul=-1;
            ch=getchar();
        }
        while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
        _=__*mul;
    }
     
    const int maxn=1e5+10;
    const int N=1e5;
    int n,m,root[maxn];
    struct node{
        ll d,p,w;
        bool operator < (const node & tt) const {
            if(d!=tt.d)return d>tt.d;
            return p<tt.p;
        }
    }a[maxn];
     
    struct Chairman_Tree{
    #define mid ((l+r)>>1)
        int cnt;
        struct poi{
            int lc,rc;
            ll sum,cost;
        }b[maxn<<5];
        void insert(int &rt,int l,int r,ll p,ll x){
            int now=++cnt; b[now]=b[rt]; rt=now;
            if(l==r)b[rt].sum+=x,b[rt].cost=b[rt].sum*l;
            else{
                if(p<=mid)insert(b[rt].lc,l,mid,p,x);
                else insert(b[rt].rc,mid+1,r,p,x);
                b[rt].sum=b[b[rt].lc].sum+b[b[rt].rc].sum;
                b[rt].cost=b[b[rt].lc].cost+b[b[rt].rc].cost;
            }
        }
        bool judge(int rt,int l,int r,ll x,ll g){
            if(x>=0 && g<0)return false;
            if(x==0 && g>=0)return true;
            if(l==r)return b[rt].sum<x ? false : (g-x*l>=0);
            ll s=b[b[rt].lc].sum,c=b[b[rt].lc].cost;
            if(s<=x)return judge(b[rt].rc,mid+1,r,x-s,g-c);
            else return judge(b[rt].lc,l,mid,x,g);
        }
    #undef mid
    }T;
     
    void init(){
        read(n),read(m);
        REP(i,1,n)read(a[i].d),read(a[i].p),read(a[i].w);
        sort(a+1,a+n+1);
        REP(i,1,n){
            root[i]=root[i-1];
            T.insert(root[i],1,N,a[i].p,a[i].w);
        }
        //REP(i,1,n)printf("%lld %lld %lld
    ",a[i].d,a[i].p,a[i].w);
    }
     
    ll calc(ll x,ll g){
        int l=1,r=n;
        while(l<r){
            int mid=(l+r)>>1;
            if(T.judge(root[mid],1,N,x,g))r=mid;
            else l=mid+1;
        }
        if(!T.judge(root[l],1,N,x,g))return -1;
        else return a[l].d;
    }
     
    void work(){
        ll g,x;
        REP(i,1,m){
            read(g),read(x);
            printf("%lld
    ",calc(x,g));
        }
    }
     
    int main(){
        //File();
        init();
        work();
        return 0;
    }
    
    
  • 相关阅读:
    第07组 Beta冲刺 总结
    第07组 Beta冲刺 (5/5)
    第07组 Beta冲刺 (4/5)
    第07组 Beta冲刺 (3/5)
    第07组 Beta冲刺 (2/5)
    第07组 Beta冲刺 (1/5)
    软工实践个人总结
    第03组 Beta冲刺(5/5)
    第03组 Beta冲刺(4/5)
    第03组 Beta冲刺(3/5)
  • 原文地址:https://www.cnblogs.com/ylsoi/p/10091179.html
Copyright © 2011-2022 走看看