题目描述
小 R 热衷于做黑暗料理,尤其是混合果汁。
商店里有 nn 种果汁,编号为 0,1,\cdots,n-10,1,⋯,n−1 。 ii 号果汁的美味度是 d_idi ,每升价格为 p_ipi 。小 R 在制作混合果汁时,还有一些特殊的规定,即在一瓶混合果汁中, ii 号果汁最多只能添加 l_ili 升。
现在有 mm 个小朋友过来找小 R 要混合果汁喝,他们都希望小 R 用商店里的果汁制作成一瓶混合果汁。其中,第 jj个小朋友希望他得到的混合果汁总价格不大于 g_jgj ,体积不小于 L_jLj 。在上述这些限制条件下,小朋友们还希望混合果汁的美味度尽可能地高,一瓶混合果汁的美味度等于所有参与混合的果汁的美味度的最小值。请你计算每个小朋友能喝到的最美味的混合果汁的美味度。
输入输出格式
输入格式:输入第一行包含两个正整数 n, mn,m ,表示果汁的种数和小朋友的数量。接下来 nn 行,每行三个正整数 d_i, p_i, l_idi,pi,li ,表示 ii 号果汁的美味度为 d_idi ,每升价格为 p_ipi ,在一瓶果汁中的添加上限为 l_ili 。
接下来 mm 行依次描述所有小朋友:每行两个数正整数 g_j, L_jgj,Lj 描述一个小朋友,表示他最多能支付 g_jgj 元钱,他想要至少 L_jLj 升果汁。
输出格式:对于所有小朋友依次输出:对于每个小朋友,输出一行,包含一个整数,表示他能喝到的最美味的混合果汁的美味度。如果无法满足他的需求,则输出 -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≤di,pi,li≤105,1≤gj,Lj≤1018 。
测试点编号 | 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=1pi=1 |
13,14,15 | 100000100000 | 100000100000 | l_i=1li=1 |
16,17,18,19,20 | 100000100000 | 100000100000 | 无 |
代码:
#include<cstdio>
#include<cctype>
#include<algorithm>
#define ll long long
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline ll read(){
ll x=0,f=1;char ch=gc();
while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
return x*f;
}
const int N=100100;
struct node{
int d,p,l;
}jui[N];
struct node1{
int left,right,v;ll sum,cnt;
}tree[N*44];
int q[N],nn,rt[N],n,m,num;ll ans1;
inline bool cmp(const node &a,const node &b){return a.d>b.d;}
inline void query(int x,int l,int r,ll p){
if (l==r){ans1+=(ll)tree[x].v*p;return;};int mid=l+r>>1;
int ls=tree[x].left;
if(p>tree[ls].cnt){
ans1+=tree[ls].sum;query(tree[x].right,mid+1,r,p-tree[ls].cnt);
}else{
query(tree[x].left,l,mid,p);
}
}
inline bool check(int md,ll lim,ll g){
ans1=0;if(tree[rt[md]].cnt<lim) return 0;
query(rt[md],1,nn,lim);
return ans1<=g;
}
inline void insert1(int &x,int l,int r,int p,int v,int lim){
tree[++num]=tree[x];x=num;tree[x].cnt+=lim;tree[x].sum+=(ll)v*lim;
if (l==r) {tree[x].v=v;return;}int mid=l+r>>1;
if (p<=mid) insert1(tree[x].left,l,mid,p,v,lim);
else insert1(tree[x].right,mid+1,r,p,v,lim);
}
ll sum;
inline void gao(){
sort(jui+1,jui+n+1,cmp);
//for (int i=1;i<=n;++i) printf("%d\n",jui[i].d);
for (int i=1;i<=n;++i) q[i]=jui[i].p,sum+=jui[i].l;
sort(q+1,q+n+1);nn=unique(q+1,q+n+1)-q-1;
for (int i=1;i<=n;++i) {
rt[i]=rt[i-1];int p=lower_bound(q+1,q+nn+1,jui[i].p)-q;
insert1(rt[i],1,nn,p,jui[i].p,jui[i].l);
}
for (int owo=1;owo<=m;++owo){
ll g=read(),lim=read();if (lim>sum) {puts("-1");continue;}
int l=1,r=n,ans;
while(l<=r){
int mid=l+r>>1;
if (check(mid,lim,g)) ans=mid,r=mid-1;else l=mid+1;
}if (l>n) {puts("-1");continue;}
// printf("%d\n",ans);
printf("%d\n",jui[ans].d);
}
}
int main(){
// freopen("juice.in","r",stdin);
// freopen("juice.out","w",stdout);
n=read();m=read();
for (int i=1;i<=n;++i){
jui[i].d=read();jui[i].p=read();jui[i].l=read();
}gao();
return 0;
}