题目
展开
题目描述
小 R 热衷于做黑暗料理,尤其是混合果汁。
商店里有 nn 种果汁,编号为 0,1,\cdots,n-10,1,⋯,n−1 。ii 号果汁的美味度是 d_id
i
,每升价格为 p_ip
i
。小 R 在制作混合果汁时,还有一些特殊的规定,即在一瓶混合果汁中,ii 号果汁最多只能添加 l_il
i
升。
现在有 mm 个小朋友过来找小 R 要混合果汁喝,他们都希望小 R 用商店里的果汁制作成一瓶混合果汁。其中,第 jj 个小朋友希望他得到的混合果汁总价格不大于 g_jg
j
,体积不小于 L_jL
j
。在上述这些限制条件下,小朋友们还希望混合果汁的美味度尽可能地高,一瓶混合果汁的美味度等于所有参与混合的果汁的美味度的最小值。请你计算每个小朋友能喝到的最美味的混合果汁的美味度。
输入格式
输入第一行包含两个正整数 n, mn,m,表示果汁的种数和小朋友的数量。接下来 nn 行,每行三个正整数 d_i, p_i, l_id
i
,p
i
,l
i
,表示 ii 号果汁的美味度为 d_id
i
,每升价格为p_ip
i
,在一瓶果汁中的添加上限为 l_il
i
。
接下来 mm 行依次描述所有小朋友:每行两个数正整数 g_j, L_jg
j
,L
j
描述一个小朋友,表示他最多能支付 g_jg
j
元钱,他想要至少 L_jL
j
升果汁。
输出格式
对于所有小朋友依次输出:对于每个小朋友,输出一行,包含一个整数,表示他能喝到的最美味的混合果汁的美味度。如果无法满足他的需求,则输出 -1−1。
输入输出样例
输入 #1复制
3 4
1 3 5
2 1 3
3 2 5
6 3
5 3
10 10
20 10
输出 #1复制
3
2
-1
1
说明/提示
对于所有的测试数据,保证 n, m \le 100000n,m≤100000,1 \le d_i,p_i,l_i \le 10^5, 1 \le g_j, L_j \le 10^{18}1≤d
i
,p
i
,l
i
≤10
5
,1≤g
j
,L
j
≤10
18
。
测试点编号 n=n= m=m= 其他限制
1,2,3 1010 1010 无
4,5,6 500500 500500 无
7,8,9 50005000 50005000 无
10,11,12 100000100000 100000100000 p_i=1p
i
=1
13,14,15 100000100000 100000100000 l_i=1l
i
=1
16,17,18,19,20 100000100000 100000100000 无
思路
首先把dd排序,枚举一个答案d,d,那么我们肯定是贪心地选择美味程度不小于dd的并且最便宜的果汁
可以发现其具有单调性,考虑二分一个d,d,给美味程度不小于dd的果汁建立一颗以价格为下标的线段树
每个节点记录一下果汁总量和价格和,这样就可以在线段树上二分得到LimLim对应的价格了
然后这个线段树是可以对dd进行可持久化的
代码
#include<bits/stdc++.h>
#define N 100005
#define ll long long
using namespace std;
struct juice{
ll d,p,l;
}x[N];
bool cmp(juice a,juice b){
return a.d<b.d;
}
int n,m,root[N],cnt;
struct node{
int l,r;
ll lit,W;
}g[N*21];
void update(int &rt,int lb,int rb,ll P,ll LIT){
g[++cnt]=g[rt];rt=cnt;g[rt].lit+=LIT;g[rt].W+=P*LIT;
if (lb==rb) return;
int mid=lb+rb>>1;
if (mid>=P) update(g[rt].l,lb,mid,P,LIT);
else update(g[rt].r,mid+1,rb,P,LIT);
}
ll query(int i,int j,int lb,int rb,ll LIT){
if (lb==rb) return 1LL*LIT*lb;
int mid=lb+rb>>1;ll TOT=g[g[j].l].lit-g[g[i].l].lit;
if (TOT>=LIT) return query(g[i].l,g[j].l,lb,mid,LIT);
return g[g[j].l].W-g[g[i].l].W+query(g[i].r,g[j].r,mid+1,rb,LIT-TOT);
}
signed main(){
n=read(),m=read();
ll MAXP=0;
for (int i=1;i<=n;i++){
x[i].d=read(),x[i].p=read(),x[i].l=read();
MAXP=max(MAXP,x[i].p);
}
sort(x+1,x+1+n,cmp);
for (int i=1;i<=n;i++){
root[i]=root[i-1];
update(root[i],1,MAXP,x[i].p,x[i].l);
}
while (m--){
ll G=read(),L=read();
ll lb=1,rb=n,ans=-1;
while (lb<=rb){
ll mid=lb+rb>>1;
if (query(root[mid-1],root[n],1,MAXP,L)<=G&&g[root[n]].lit-g[root[mid-1]].lit>=L){
lb=mid+1;ans=mid;
}else{
rb=mid-1;
}
}
if (ans==-1) printf("-1\n");
else printf("%lld\n",x[ans].d);
}
}