zoukankan      html  css  js  c++  java
  • 题解 洛谷 P4602 【[CTSC2018]混合果汁】

    注意到问题具有单调性,所以一个询问可以通过二分答案来解决。

    对于多组询问,就采用整体二分来处理。

    将果汁按(d)从大到小排序,二分出一个位置(mid),只考虑在位置(mid)之前的果汁,其中位置(mid)的果汁的(d)即为二分出的所有参与混合的果汁的美味度的最小值。

    在判断一个(mid)合不合法时,将其之前所有果汁的体积的前缀和和各自的体积乘价格前缀和处理出来,后者就是买下所有果汁的价格。

    然后对于一个询问,再进行一次二分,找到最小的价格来满足其体积的需求,然后就可以判断一个(mid)是否合法了。

    对于前缀和的操作,可以通过树状数组来实现,随着(mid)的改变调整即可。

    具体实现细节看代码吧。

    (code)

    #include<bits/stdc++.h>
    #define maxn 200010
    #define inf 1000000000000000000
    #define lowbit(x) (x&(-x))
    using namespace std;
    typedef long long ll;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    ll n,m,now,ma;
    ll ans[maxn];
    struct node
    {
        ll d,p,l;
    }t[maxn];
    bool cmp(const node &a,const node &b)
    {
        return a.d>b.d;
    }
    struct query
    {
        ll g,l;
        int id;
    }q[maxn],q1[maxn],q2[maxn];
    struct Tree
    {
        ll tr[maxn];
        void update(int x,ll v)
        {
            while(x<=ma)
                tr[x]+=v,x+=lowbit(x);
        }
        ll query(int x)
        {
            ll sum=0;
            while(x)
                sum+=tr[x],x-=lowbit(x);
            return sum;
        }
    }Li,Pr;
    void change(int x,int type)
    {
        Li.update(t[x].p,type*t[x].l),Pr.update(t[x].p,type*t[x].p*t[x].l);
    }
    ll find(int x)
    {
        int l=1,r=ma,pr=ma;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(Li.query(mid)>=q[x].l) pr=mid,r=mid-1;
            else l=mid+1;
        }
        return pr;
    }
    void solve(int L,int R,int l,int r)
    {
        if(L>R) return;
        if(l==r)
        {
            for(int i=L;i<=R;++i) ans[q[i].id]=t[l].d;
            return;
        }
        int mid=(l+r)>>1;
        while(now<mid) change(++now,1);
        while(now>mid) change(now--,-1);
        int cnt1=0,cnt2=0;
        for(int i=L;i<=R;++i)
        {
            ll pr=find(i),lv=Li.query(pr),pv=Pr.query(pr);
            if(lv>=q[i].l&&pv-pr*(lv-q[i].l)<=q[i].g) q1[++cnt1]=q[i];
            else q2[++cnt2]=q[i];
        }
        for(int i=1;i<=cnt1;++i) q[L+i-1]=q1[i];
        for(int i=1;i<=cnt2;++i) q[L+cnt1+i-1]=q2[i];
        solve(L,L+cnt1-1,l,mid),solve(L+cnt1,R,mid+1,r);
    }
    int main()
    {
        read(n),read(m);
        for(int i=1;i<=n;++i)
            read(t[i].d),read(t[i].p),read(t[i].l),ma=max(ma,t[i].p);
        t[++n].d=-1,t[n].p=1,t[n].l=inf,sort(t+1,t+n+1,cmp);
        for(int i=1;i<=m;++i) read(q[i].g),read(q[i].l),q[i].id=i;
        solve(1,m,1,n);
        for(int i=1;i<=m;++i) printf("%lld
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    Python之struct模块浅谈
    看头发知健康
    ZeroMQ:云计算时代最好的通讯库
    粗盐热敷疗法经验汇总
    百度2011校招笔试算法题一
    new/delete 和malloc/free 的区别一般汇总
    Trie字典树
    百度2012校招笔试题之全排列与组合
    百度2011校招笔试算法题二
    执行程序的内存分布总结
  • 原文地址:https://www.cnblogs.com/lhm-/p/12630109.html
Copyright © 2011-2022 走看看