传送门:bzoj5343
可以二分一个答案 d d d,每次贪心从美味度 ≥ d \geq d ≥d的 p p p最小的选起(尽可能地选更大体积的饮料),所以最优选择方案也是固定的。按 d d d建主席树。二分查询即可。
#include
#define RI register
#define gc getchar()
#define si isdigit(ch)
#define lc(k) t[(k)].ch[0]
#define rc(k) t[(k)].ch[1]
#define mid (((l)+(r))>>1)
using namespace std;
const int N=1e5+10;
typedef long long ll;
int n,m,cs,P[2],D[N];
ll G,V;
int cnt,rt[N];
struct juice{
int d,p,l;
bool operator <(const juice&ky)const{
return d<ky.d;
}
}drk[N];
struct node{
int ch[2];ll sv,sc;
node(){};
node(int sonl,int sonr,ll sv_,ll sc_){ch[0]=sonl;ch[1]=sonr;sv=sv_;sc=sc_;}
}t[N*33];
char ch;
template<class T>
inline void rd(T &x)
{
ch=gc;x=0;
for(;!si;ch=gc);
for(;si;ch=gc) x=x*10+(ch^48);
}
inline void ins(int pre,int &k,int l,int r,int pos,int vv)
{
if(k==pre) t[(k=++cnt)]=node(lc(pre),rc(pre),t[pre].sv,t[pre].sc);
t[k].sv+=vv;t[k].sc+=1ll*pos*vv;
if(l==r) return;
if(pos<=mid) ins(lc(pre),lc(k),l,mid,pos,vv);
else ins(rc(pre),rc(k),mid+1,r,pos,vv);
}
inline ll query(int pre,int k,int l,int r,ll res)
{
if(!k) return 0;
if(l==r) return min(res/l,t[k].sv-t[pre].sv);
ll sum=t[lc(k)].sc-t[lc(pre)].sc;
if(res<=sum) return query(lc(pre),lc(k),l,mid,res);
return t[lc(k)].sv-t[lc(pre)].sv+query(rc(pre),rc(k),mid+1,r,res-sum);
}
int main(){
RI int i,j,l,r,ans;
rd(n);rd(m);P[0]=N;
for(i=1;i<=n;++i){
rd(drk[i].d),rd(drk[i].p),rd(drk[i].l);
P[0]=min(P[0],drk[i].p);P[1]=max(P[1],drk[i].p);
}
sort(drk+1,drk+n+1);
D[(cs=1)]=drk[1].d;
for(i=1;i<=n;++i){
if(D[cs]!=drk[i].d){D[++cs]=drk[i].d;rt[cs]=rt[cs-1];}
ins(rt[cs-1],rt[cs],P[0],P[1],drk[i].p,drk[i].l);
}
for(;m;--m){
rd(G);rd(V);
l=1;r=cs;ans=-1;
for(;l<=r;){
if(query(rt[mid-1],rt[cs],P[0],P[1],G)>=V){
ans=D[mid];l=mid+1;
}else r=mid-1;
}
printf("%d\n",ans);
}
return 0;
}