zoukankan      html  css  js  c++  java
  • 【BZOJ5343】混合果汁(CTSC2018)-二分答案+主席树

    测试地址:混合果汁
    做法:本题需要用到二分答案+主席树。
    注意到,如果一个最小美味度为d的混合果汁可以配出,那么最小美味度<d的所有可能的混合果汁也可以配出,这个性质具有单调性,所以我们可以二分最小美味度d,问题转化成判定性问题。
    判定的话也很简单,容易想到贪心选取最便宜的L升果汁,然后看它们的总价值,如果不超过G,就代表可以配出,否则就不能配出。那么我们可以按果汁的价值建线段树,每个区间维护区间内所有果汁的体积和与它们的价值总和,那么在线段树上二分就可解决上面问题。
    另外,注意到这棵线段树是可以按美味度可持久化的,于是我们就用O(nlog2n)解决了这个问题。
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int n,m,maxp,tot=0,rt[100010],ch[2000010][2];
    ll seg[2000010],sum[2000010];
    struct juice
    {
        int d;
        ll p,l;
    }q[100010];
    
    bool cmp(juice a,juice b)
    {
        if (a.d!=b.d) return a.d<b.d;
        else return a.p<b.p;
    }
    
    void buildtree(int &no,int l,int r)
    {
        no=++tot;
        seg[no]=sum[no]=0;
        if (l==r) return;
        int mid=(l+r)>>1;
        buildtree(ch[no][0],l,mid);
        buildtree(ch[no][1],mid+1,r);
    }
    
    void insert(int &no,int last,int l,int r,ll x,ll L)
    {
        no=++tot;
        seg[no]=seg[last];
        sum[no]=sum[last];
        ch[no][0]=ch[last][0],ch[no][1]=ch[last][1];
        if (l==r)
        {
            seg[no]+=L;
            sum[no]+=x*L;
            return;
        }
        int mid=(l+r)>>1;
        if (x<=mid) insert(ch[no][0],ch[last][0],l,mid,x,L);
        else insert(ch[no][1],ch[last][1],mid+1,r,x,L);
        seg[no]=seg[ch[no][0]]+seg[ch[no][1]];
        sum[no]=sum[ch[no][0]]+sum[ch[no][1]];
    }
    
    ll query(int last,int no,int l,int r,ll L)
    {
        ll totsum,s;
        int mid=(l+r)>>1;
        if (l==r) return (ll)l*L;
        if (seg[ch[no][0]]-seg[ch[last][0]]<L)
        {
            totsum=sum[ch[no][0]]-sum[ch[last][0]];
            s=seg[ch[no][0]]-seg[ch[last][0]];
            return totsum+query(ch[last][1],ch[no][1],mid+1,r,L-s);
        }
        else return query(ch[last][0],ch[no][0],l,mid,L);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        maxp=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%lld%lld",&q[i].d,&q[i].p,&q[i].l);
            maxp=max(maxp,(int)q[i].p);
        }
        sort(q+1,q+n+1,cmp);
        buildtree(rt[0],1,maxp);
        for(int i=1;i<=n;i++)
            insert(rt[i],rt[i-1],1,maxp,q[i].p,q[i].l);
    
        for(int i=1;i<=m;i++)
        {
            ll G,L;
            scanf("%lld%lld",&G,&L);
            int l=0,r=n;
            while(l<r)
            {
                int mid=(l+r)>>1;
                if (seg[rt[n]]-seg[rt[mid]]<L) {r=mid;continue;}
                if (query(rt[mid],rt[n],1,maxp,L)<=G) l=mid+1;
                else r=mid;
            }
            if (l==0) printf("-1
    ");
            else printf("%d
    ",q[l].d);
        }
    
        return 0;
    }
  • 相关阅读:
    Fish
    Brackets
    StoneWall【★★★★★】
    Nesting
    ajax补充FormData
    初始Ajax
    extra过滤
    Django 之缓存
    django中的信号
    Form组件归类
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793365.html
Copyright © 2011-2022 走看看