BZOJ5343 & 洛谷4602 & LOJ2555:[CTSC2018]混合果汁——题解
https://www.luogu.org/problemnew/show/P4602
https://www.lydsy.com/JudgeOnline/problem.php?id=5343
小 R 热衷于做黑暗料理,尤其是混合果汁。
商店里有 n 种果汁,编号为 0,1,2,...,n−1。i 号果汁的美味度是 di,每升价格为 pi。小 R 在制作混合果汁时,还有一些特殊的规定,即在一瓶混合果汁中,i 号果汁最多只能添加 li 升。
现在有 m 个小朋友过来找小 R 要混合果汁喝,他们都希望小 R 用商店里的果汁制作成一瓶混合果汁。其中,第 j 个小朋友希望他得到的混合果汁总价格不大于 gj,体积不小于 Lj。在上述这些限制条件下,小朋友们还希望混合果汁的美味度尽可能地高,一瓶混合果汁的美味度等于所有参与混合的果汁的美味度的最小值。请你计算每个小朋友能喝到的最美味的混合果汁的美味度。
比较简单……前提是不会把题看成“果汁美味度=美味度之和”。
这样一来我们先对美味度排序,然后二分答案,就可以知道我们只可以取k~n的果汁,然后判断是否可行即可。
贪心的思路:我们按照p从小到大取果汁是最优的。
主席树显然可以胜任这个工作。
#include<cmath> #include<cstdio> #include<cctype> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N=1e5+5; inline ll read(){ ll X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct juice{ int d,p,l; }a[N]; struct tree{ int l,r; ll v,s; }tr[N*20]; int n,m,t,pos[N],rt[N],pool; inline bool cmp(juice a,juice b){ return a.d<b.d; } inline void insert(int y,int &x,int l,int r,int p,int v){ tr[x=++pool]=tr[y]; tr[x].v+=(ll)p*v;tr[x].s+=v; if(l==r)return; int mid=(l+r)>>1; if(p<=mid)insert(tr[y].l,tr[x].l,l,mid,p,v); else insert(tr[y].r,tr[x].r,mid+1,r,p,v); } inline ll query(int nl,int nr,int l,int r,ll p){ if(l==r)return min(p/l,tr[nr].s-tr[nl].s); ll delta=tr[tr[nr].l].v-tr[tr[nl].l].v; ll tmp=tr[tr[nr].l].s-tr[tr[nl].l].s; int mid=(l+r)>>1; if(delta>p)return query(tr[nl].l,tr[nr].l,l,mid,p); else return tmp+query(tr[nl].r,tr[nr].r,mid+1,r,p-delta); } ll G,L; bool pan(int k){ ll tmp=query(rt[k-1],rt[n],1,1e5,G); return tmp>=L; } ll solve(int l,int r){ while(l<r){ int mid=(l+r+1)>>1; if(pan(pos[mid]))l=mid; else r=mid-1; } return pan(pos[l])?a[pos[l]].d:-1; } int main(){ n=read(),m=read(); for(int i=1;i<=n;i++) a[i].d=read(),a[i].p=read(),a[i].l=read(); sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++){ if(a[pos[t]].d!=a[i].d)pos[++t]=i; insert(rt[i-1],rt[i],1,1e5,a[i].p,a[i].l); } for(int i=1;i<=m;i++){ G=read(),L=read(); printf("%lld\n",solve(1,t)); } return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +
+++++++++++++++++++++++++++++++++++++++++++