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

    题目链接:

    CTSC2018混合果汁

    显然如果美味度高的合法那么美味度低的一定合法,因为美味度低的可选方案包含美味度高的可选方案。

    那么我们二分一个美味度作为答案然后考虑如何验证?

    选择时显然要贪心的先选单价低的果汁。

    那么我们按美味度从大到小将每种果汁排序,然后对于每种果汁建立一个版本的主席树,主席树维护的权值是果汁单价。

    每次验证时在对应版本主席树中查找,如果左子树中总体积大于L则递归左子树,否则将答案加上左子树所有果汁的总价然后递归右子树。

    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<vector>
    #include<bitset>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    struct miku
    {
        int d;
        ll g,l;
    }s[100010];
    int cnt;
    int n,m,q;
    ll G,L;
    int ls[2000010];
    int rs[2000010];
    ll sum[2000010];
    ll num[2000010];
    int root[100010];
    ll h[100010];
    bool cmp(miku a,miku b)
    {
        if(a.d!=b.d)
        {
            return a.d>b.d;
        }
        return a.g<b.g;
    }
    void updata(int &rt,int pre,int l,int r,int x,ll val,ll lim)
    {
        rt=++cnt;
        sum[rt]=sum[pre]+val;
        num[rt]=num[pre]+lim;
        ls[rt]=ls[pre];
        rs[rt]=rs[pre];
        if(l==r)
        {
            return ;
        }
        int mid=(l+r)>>1;
        if(x<=mid)
        {
            updata(ls[rt],ls[pre],l,mid,x,val,lim);
        }
        else
        {
            updata(rs[rt],rs[pre],mid+1,r,x,val,lim);
        }
    }
    ll query(int rt,int l,int r,ll k)
    {
        if(l==r)
        {
            return k*h[l];
        }
        int mid=(l+r)>>1;
        if(num[ls[rt]]>=k)
        {
            return query(ls[rt],l,mid,k);
        }
        else
        {
            return sum[ls[rt]]+query(rs[rt],mid+1,r,k-num[ls[rt]]);
        }
    }
    bool check(int x)
    {
        if(num[root[x]]<L)
        {
            return false;
        }
        if(query(root[x],1,m,L)<=G)
        {
            return true;
        }
        return false;
    }
    int main()
    {
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%lld%lld",&s[i].d,&s[i].g,&s[i].l);
            h[i]=s[i].g;
        }
        sort(s+1,s+1+n,cmp);
        sort(h+1,h+1+n);
        m=unique(h+1,h+1+n)-h-1;
        for(int i=1;i<=n;i++)
        {
            updata(root[i],root[i-1],1,m,lower_bound(h+1,h+1+m,s[i].g)-h,s[i].g*s[i].l,s[i].l);
        }
        while(q--)
        {
            scanf("%lld%lld",&G,&L);
            int l=1;
            int r=n;
            int ans=-1;
            while(l<=r)
            {
                int mid=(l+r)>>1;
                if(check(mid)==true)
                {
                    ans=mid;
                    r=mid-1;
                }
                else
                {
                    l=mid+1;
                }
            }
            if(ans==-1)
            {
                printf("-1
    ");
                continue;
            }
            printf("%d
    ",s[ans].d);
        }
    }
  • 相关阅读:
    vagrant up报错 Warning: Authentication failure. Retrying...解决方案
    node读写Excel操作
    批量转换word为pdf
    分享7个shell脚本实例--shell脚本练习必备
    shell脚本实例,通向shell脚本大师的必经之路
    前端优化DNS预解析
    如何选择开源协议
    深入理解document.referrer的用法
    使用 WebRTC 构建简单的前端视频通讯
    深入理解WebRTC
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/10028956.html
Copyright © 2011-2022 走看看