BZOJphp
洛谷ios
果真改了題仍是寫一下題解影響深入啊,以前互測還作過增強版,結果今天仍是沒寫出來……ui
顯然能夠二分答案,問題在於快速判斷是否可行spa
把全部果汁按美味度由大到小排序後,只能選擇\(mid\)左邊的rest
從價格最小的開始選必定最優,因此咱們能夠以價格爲下標構建線段樹,維護總花費和總數量,在線段樹上查找花費必定時最大數量便可code
題目有多組詢問,但果汁的順序不變,能夠主席樹維護排序
注意判斷數量不夠的狀況get
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAXN 100005 typedef long long LL; struct ChairmanTree { struct Node { Node *ls, *rs; LL cost, amount; } * root[MAXN]; void build(); void update(Node *, Node *, int, int, int, LL); LL query(Node *, int, int, LL); }; struct Juice { int deli, price, amount; bool operator <(const Juice &j) const { return deli > j.deli; } }; int N, M; Juice juice[MAXN]; ChairmanTree tr; char gc(); LL read(); int main() { N = read(), M = read(); for (int i = 1; i <= N; ++i) { juice[i].deli = read(); juice[i].price = read(); juice[i].amount = read(); } std::sort(juice + 1, juice + N + 1); tr.build(); while (M--) { LL money = read(), demand = read(); int l = 1, r = N; while (l < r) { int mid = (l + r) >> 1; LL least = tr.query(tr.root[mid], 1, 100000, demand); if ((~least) &&least <= money) r = mid; else l = mid + 1; } LL least = tr.query(tr.root[l], 1, 100000, demand); if ((~least) && least <= money) printf("%d\n", juice[l].deli); else puts("-1"); } return 0; } inline char gc() { static char buf[1000000], *p1, *p2; if (p1 == p2) p1 = (p2 = buf) + fread(buf, 1, 1000000, stdin); return p1 == p2 ? EOF : *p2++; } inline LL read() { LL res = 0; char ch = gc(); while (ch < '0' || ch > '9') ch = gc(); while (ch >= '0' && ch <= '9') res = (res << 1) + (res << 3) + ch - '0', ch = gc(); return res; } void ChairmanTree::build() { for (int i = 1; i <= N; ++i) update(root[i - 1], root[i] = new Node(), 1, 100000, juice[i].price, juice[i].amount); } void ChairmanTree::update(Node *pre, Node *cur, int L, int R, int pos, LL val) { if (L == R) cur->amount = (pre ? pre->amount : 0) + val, cur->cost = (pre ? pre->cost : 0) + val * pos; else { int mid = (L + R) >> 1; if (pos <= mid) { cur->rs = (pre ? pre->rs : 0); update(pre ? pre->ls : 0, cur->ls = new Node(), L, mid, pos, val); } else { cur->ls = (pre ? pre->ls : 0); update(pre ? pre->rs : 0, cur->rs = new Node(), mid + 1, R, pos, val); } cur->amount = (cur->ls ? cur->ls->amount : 0) + (cur->rs ? cur->rs->amount : 0); cur->cost = (cur->ls ? cur->ls->cost : 0) + (cur->rs ? cur->rs->cost : 0); } } LL ChairmanTree::query(Node *rt, int L, int R, LL rest) { if (!rt || rt->amount < rest) return -1; if (L == R) return L * rest; int mid = (L + R) >> 1; LL amt = (rt->ls ? rt->ls->amount : 0), cst = (rt->ls ? rt->ls->cost : 0); if (amt >= rest) return query(rt->ls, L, mid, rest); else return cst + query(rt->rs, mid + 1, R, rest - amt); } //Rhein_E