Luogu 4602 [CTSC2018]混合果汁
BZOJ 5343
福利题。
对于每一个询问可以二分$d$,然后把满足条件的果汁按照$p$从小到大排序贪心地取$L$升看看满不满足价格的条件。
那么按照$p$建立权值主席树,$chk$的时候在主席树上走一走算出价格即可。
当然也可以整体二分。
时间复杂度都是$O(nlog^2n)$。
Code:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N = 1e5 + 5; const ll inf = 1LL << 60; int n, qn, tot = 0, pos[N], buc[N]; struct Item { int d, cost, lim; inline Item(int D = 0, int Cost = 0, int Lim = 0) { d = D, cost = Cost, lim = Lim; } friend bool operator < (const Item x, const Item y) { return x.d > y.d; } } a[N]; namespace Fread { const int L = 1 << 15; char buffer[L], *S, *T; inline char Getchar() { if(S == T) { T = (S = buffer) + fread(buffer, 1, L, stdin); if(S == T) return EOF; } return *S++; } template <class T> inline void read(T &X) { char ch; T op = 1; for(ch = Getchar(); ch > '9' || ch < '0'; ch = Getchar()) if(ch == '-') op = -1; for(X = 0; ch >= '0' && ch <= '9'; ch = Getchar()) X = (X << 1) + (X << 3) + ch - '0'; X *= op; } } using namespace Fread; namespace Fwrite { const int L = 1 << 15; char buf[L], *pp = buf; void Putchar(const char c) { if(pp - buf == L) fwrite(buf, 1, L, stdout), pp = buf; *pp++ = c; } template<typename T> void print(T x) { if(x < 0) { Putchar('-'); x = -x; } if(x > 9) print(x / 10); Putchar(x % 10 + '0'); } void fsh() { fwrite(buf, 1, pp - buf, stdout); pp = buf; } template <typename T> inline void write(T x, char ch = 0) { print(x); if (ch != 0) Putchar(ch); fsh(); } } using namespace Fwrite; namespace SegT { struct Node { int lc, rc; ll sum, cnt; } s[N * 30]; int root[N], nodeCnt = 0; #define lc(p) s[p].lc #define rc(p) s[p].rc #define sum(p) s[p].sum #define cnt(p) s[p].cnt #define mid ((l + r) >> 1) void ins(int &p, int l, int r, int x, int v, int pre) { s[p = ++nodeCnt] = s[pre]; cnt(p) += 1LL * v, sum(p) += 1LL * v * buc[x]; if (l == r) return; if (x <= mid) ins(lc(p), l, mid, x, v, lc(pre)); else ins(rc(p), mid + 1, r, x, v, rc(pre)); } ll query(int p, int l, int r, ll cur) { if (l == r) return cur > cnt(p) ? inf : cur * buc[l]; ll now = cnt(lc(p)); if (cur <= now) return query(lc(p), l, mid, cur); else return sum(lc(p)) + query(rc(p), mid + 1, r, cur - now); } #undef mid } using namespace SegT; inline bool chk(int mid, ll x, ll y) { if (cnt(root[pos[a[mid].d]]) < y) return 0; ll now = query(root[pos[a[mid].d]], 1, tot, y); return now <= x; } int main() { #ifndef ONLINE_JUDGE freopen("Sample.txt", "r", stdin); #endif read(n), read(qn); for (int i = 1; i <= n; i++) { read(a[i].d), read(a[i].cost), read(a[i].lim); buc[++tot] = a[i].cost; } sort(buc + 1, buc + 1 + tot); tot = unique(buc + 1, buc + 1 + tot) - buc - 1; for (int i = 1; i <= n; i++) a[i].cost = lower_bound(buc + 1, buc + 1 + tot, a[i].cost) - buc; sort(a + 1, a + 1 + n); for (int i = 1; i <= n; i++) { ins(root[i], 1, tot, a[i].cost, a[i].lim, root[i - 1]); pos[a[i].d] = i; } for (ll x, y; qn--; ) { read(x), read(y); /* if (y > cnt(root[n])) { puts("-1"); continue; } */ int ln = 1, rn = n, mid, res = 0; for (; ln <= rn; ) { mid = (ln + rn) / 2; if (chk(mid, x, y)) rn = mid - 1, res = mid; else ln = mid + 1; } write((!res) ? -1 : a[res].d, '\n'); } return 0; }