[CTSC2018]混合果汁

题意

n n 种果汁, i i 种果汁的美味程度是di, li l i , , 价格是pi/

m m 个询问,要求使用果汁的总量不小于 Lim, L i m , 价格不超过 G, G , 最大化所用的果汁的美味程度最小值


先开最简单的题

似乎好久没写 Blog B l o g ( ( 大雾


题解

首先把d排序 , , 枚举一个答案d,那么我们肯定是贪心地选择美味程度不小于 d d 的并且最便宜的果汁

可以发现其具有单调性,考虑二分一个 d, d , 给美味程度不小于 d d 的果汁建立一颗以价格为下标的线段树

每个节点记录一下果汁总量和价格和,这样就可以在线段树上二分得到 Lim L i m 对应的价格了

然后这个线段树是可以对 d d 进行可持久化的

复杂度O(nlog2n)

#include<bits/stdc++.h>
#define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define go(u) for(register int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
char ss[1<<17],*A=ss,*B=ss;
inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
template<class T>inline void sd(T&x){
    char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45)y=-1;x=c-48;
    while(c=gc(),47<c&&c<58)x=x*10+c-48;x*=y;
}
char sr[1<<21],z[20];int C=-1,Z;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
template<class T>inline void we(T x){
    if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=1e5+5,M=1e5;
typedef int arr[N];
typedef long long ll;
struct Juice{
    int d,p,l;
    inline void init(){sd(d),sd(p),sd(l);}
    inline bool operator<(const Juice b){return d<b.d;}
}a[N];
struct Pt{int l,r;ll s,w;}tr[N*20];
int n,m,pt;arr T;
void ins(int&p,int L,int R,int x,int s,ll w){
    tr[++pt]=tr[p],p=pt;tr[p].s+=s,tr[p].w+=w;
    if(L==R)return;int mid=(L+R)>>1;
    if(x<=mid)ins(tr[p].l,L,mid,x,s,w);
    else ins(tr[p].r,mid+1,R,x,s,w);
}
ll qry(int p,int L,int R,ll s){
    if(L==R)return s*L;int mid=(L+R)>>1;
    if(s<=tr[tr[p].l].s)return qry(tr[p].l,L,mid,s);
    return tr[tr[p].l].w+qry(tr[p].r,mid+1,R,s-tr[tr[p].l].s);
}
inline void sol(){
    ll G,Lim;sd(G),sd(Lim);
    int L=0,R=M,mid,tp=0;
    while(L<=R){
        mid=(L+R)>>1;
        if(Lim<=tr[T[mid]].s&&qry(T[mid],0,M,Lim)<=G)tp=mid,L=mid+1;
        else R=mid-1;
    }we(a[tp].d);
}
int main(){
    #ifndef ONLINE_JUDGE
        file("s");
    #endif
    sd(n),sd(m);a[0].d=-1;
    fp(i,1,n)a[i].init();
    sort(a+1,a+n+1);
    fd(i,n,1)ins(T[i]=T[i+1],0,M,a[i].p,a[i].l,(ll)a[i].p*a[i].l);
    T[0]=T[1];while(m--)sol();
return Ot(),0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值