题解 P4602 【[CTSC2018]混合果汁】
题解 P4602 【[CTSC2018]混合果汁】
洛谷题面传送门
一眼就能看出,这道题可以二分答案。
假设二分出的果汁最小美味值是
接下来我们就要想怎么
所以关键问题是价格,再看数据范围,只够我们再加一个
现在,我们想如何按照我们的贪心思路在主席树上查询。假设我们现在在节点
因此,我们在主席树中就要存两个信息。一是对应区间的果汁数量,而是对应区间果汁全取的价格。
最后,贪心取出的价格如果
下面是 AC 代码
/*
luogu P4602
*/
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define mid (l+r>>1)
const int N = 1e5;
int n,q,ans;
struct juice{
int d,p,m;
bool operator < (const juice b) const
{
return d>b.d;
}
}a[100005];
int cnt,root[100005];
struct hjtree{
int l,r,s,sum;
}t[100005<<6];
void insert(int &o,int pre,int l,int r,int x,int v)
{
o = ++cnt;
t[o] = t[pre];
t[o].s += v, t[o].sum += x*v;
if(l==x && r==x)
return;
if(x<=mid)
insert(t[o].l,t[pre].l,l,mid,x,v);
else
insert(t[o].r,t[pre].r,mid+1,r,x,v);
}
int query(int o,int l,int r,int k)
{
if(l==r)
return l*k;
if(t[t[o].l].s>=k)
return query(t[o].l,l,mid,k);
else
return t[t[o].l].sum+query(t[o].r,mid+1,r,k-t[t[o].l].s);
}
signed main()
{
cin>>n>>q;
for(int i=1;i<=n;cin>>a[i].d>>a[i].p>>a[i].m,i++);
sort(a+1,a+1+n);
for(int i=1;i<=n;i++)
insert(root[i],root[i-1],1,N,a[i].p,a[i].m);
while(q--)
{
int g,lim;
cin>>g>>lim;
ans = -1;
int l=1,r=n;
while(l<=r)
{
int res=query(root[mid],1,N,lim);
if(res<=g && t[root[mid]].s>=lim)
ans = mid, r = mid-1;
else
l = mid+1;
}
cout<<(ans==-1 ? -1 : a[ans].d)<<endl;
}
}
祝大家 AC 愉快!