[CTSC2018]混合果汁 二分 套 主席树上二分

Posted 昵称很长很长真是太好了

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CTSC2018]混合果汁 二分 套 主席树上二分相关的知识,希望对你有一定的参考价值。

题意:
n种果汁,第iii种果汁的美味程度是 d i d_i di l i l_i li​升,价格是 p i p_i pi
m m m个询问,要求使用果汁的总量不小于 L i m Lim Lim,价格不超过 G G G,最大化所用的果汁的美味程度最小值
思路:
大体思路:
首先二分出来一个taste,然后在比taste高的里面去找一些价格少的,且能凑到L升的果汁,检查是否能凑出。
我们发现题目询问很多次,那么我们对于每一次的询问二分,在二分检查时肯定不可以O(n)去检查,因为这样时间复杂度就变成了 O ( m ∗ n ∗ l o g n ) O(m*n*logn) O(mnlogn)了,我么利用主席树。

首先把按照 t a s t e taste taste排序,二分一个答案 t a s t e taste taste,那么我们肯定是贪心地选择美味程度不小于 t a s t e taste taste的并且最便宜的果汁
可以发现其具有单调性,考虑二分一个 t a s t e taste taste给美味程度不小于 t a s t e taste taste的果汁建立一颗以价格为下标的线段树
每个节点记录一下果汁总量和价格和,这样就可以在线段树上二分得到 L L L对应的价格了
代码:

#include<bits/stdc++.h>
//#define int long long
#define endl '\\n'
using namespace std;

const int maxn=1e5+10;

struct E
    int taste,price,v;
    bool operator <(const E & a)const
    return taste<a.taste;
    
a[maxn];

int n,m,cnt;
int rt[maxn];
long long treecost[maxn*50],treesum[maxn*50];
int ls[maxn*50],rs[maxn*50];


void updata(int &node,int start,int ends,int lst,long long pos,long long val)  //val 多少升
    node=++cnt;
    ls[node]=ls[lst];
    rs[node]=rs[lst];
    treecost[node]=treecost[lst]+pos*val;
    treesum[node]=treesum[lst]+val;
    if(start==ends) return ;
    int mid=(start+ends)>>1;
    if(pos<=mid) updata(ls[node],start,mid,ls[lst],pos,val);
    else updata(rs[node],mid+1,ends,rs[lst],pos,val);


long long sumnow;

//sum 表示的是容积

bool query(int start,int ends,int x,int y,long long rem)
    if(treesum[y]-treesum[x]<rem) return false;
    if(start==ends)
        sumnow+=rem*start;
        return true;
    
    int mid=(start+ends)>>1;
    long long lsum=treesum[ls[y]]-treesum[ls[x]];
    if(lsum>=rem)
        return query(start,mid,ls[x],ls[y],rem);
    
    else
        sumnow+=treecost[ls[y]]-treecost[ls[x]];
        return query(mid+1,ends,rs[x],rs[y],rem-lsum);
    


int imax=1;
bool che(int x,long long cost,long long tot)
    sumnow=0;
    if(query(1,imax,rt[x-1],rt[n],tot)==false) return false;

    return sumnow<=cost;




signed main()
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin>>n>>m;

    for(int i=1;i<=n;i++)
        cin>>a[i].taste>>a[i].price>>a[i].v;
        imax=max(imax,a[i].price);
    
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++)
        updata(rt[i],1,imax,rt[i-1],a[i].price,a[i].v);
    
    for(int i=1;i<=m;i++)
        long long pric,L;
        cin>>pric>>L;
        int l=1,r=n,ans=-1;
        while(l<=r)
            int mid=(l+r)>>1;
            if(che(mid,pric,L))
                ans=a[mid].taste;
                l=mid+1;
            
            else r=mid-1;
        

        cout<<ans<<endl;

    




以上是关于[CTSC2018]混合果汁 二分 套 主席树上二分的主要内容,如果未能解决你的问题,请参考以下文章

[CTSC2018]混合果汁 二分 套 主席树上二分

[CTSC2018]混合果汁 二分 套 主席树上二分

uoj#402. CTSC2018混合果汁(主席树+二分)

BZOJ5343 [Ctsc2018]混合果汁 二分 + 主席树

[ctsc2018] 混合果汁 主席树二分答案

[CTSC2018]混合果汁