Address
Solution
看到要最大化最小值,显然二分。
先将所有的果汁按照美味度从大到小排序。
转化成判定性问题:在所有果汁的一个前缀
中,是否能选出一些果汁使得价格不超过
,体积不小于
。
显然,我们一定要让体积等于
,并且要从单位价格低的果汁开始选。
把排序之后的果汁建成主席树,下标为单位价格。
主席树上存储体积之和以及价格之和。
可以在主席树上二分求得最小价格。
如果得到的最小价格不超过
,那么向左调整。
否则向右调整。
Code
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define For(i, a, b) for (i = a; i <= b; i++)
inline int read()
{
int res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
return bo ? ~res + 1 : res;
}
typedef long long ll;
inline ll readll()
{
ll res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
return bo ? ~res + 1 : res;
}
const int N = 1e5 + 5, M = 3e6 + 5, MP = 1e5;
const ll INF = 2e18;
int n, m, ToT, rt[N];
struct edon
{
int d, p, l;
} a[N];
struct node
{
int lc, rc; ll sum, prc;
} T[M];
bool comp(edon a, edon b)
{
return a.d > b.d;
}
void ins(int y, int &x, int l, int r, int p, ll add)
{
T[x = ++ToT] = T[y];
T[x].sum += add; T[x].prc += add * p;
if (l == r) return;
int mid = l + r >> 1;
if (p <= mid) ins(T[y].lc, T[x].lc, l, mid, p, add);
else ins(T[y].rc, T[x].rc, mid + 1, r, p, add);
}
ll ask(int x, int l, int r, ll lp)
{
if (lp > T[x].sum) return INF;
if (l == r) return lp * l;
int mid = l + r >> 1;
if (lp <= T[T[x].lc].sum) return ask(T[x].lc, l, mid, lp);
else return ask(T[x].rc, mid + 1, r, lp - T[T[x].lc].sum)
+ T[T[x].lc].prc;
}
int main()
{
int i;
ll g, L;
n = read(); m = read();
For (i, 1, n) a[i].d = read(), a[i].p = read(), a[i].l = read();
std::sort(a + 1, a + n + 1, comp);
For (i, 1, n) ins(rt[i - 1], rt[i], 1, MP, a[i].p, a[i].l);
while (m--)
{
g = readll(); L = readll();
int l = 1, r = n;
while (l <= r)
{
int mid = l + r >> 1;
if (ask(rt[mid], 1, MP, L) <= g) r = mid - 1;
else l = mid + 1;
}
if (l == n + 1) puts("-1");
else printf("%d\n", a[l].d);
}
return 0;
}