1. 程式人生 > >BZOJ5343 [Ctsc2018]混合果汁 【二分 + 主席樹】

BZOJ5343 [Ctsc2018]混合果汁 【二分 + 主席樹】

char 明顯 TP mem size sin ret flag truct

題目鏈接

BZOJ5343

題解

明顯要二分一下美味度,然後用盡量少的價格去購買飲料,看看能否買到\(L\)升,然後看看能否控制價格在\(g\)
盡量少的價格,就優先先選完便宜的飲料,由於詢問的是一定美味度範圍的,主席樹上詢問即可

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++) #define mp(a,b) make_pair<int,int>(a,b) #define cls(s) memset(s,0,sizeof(s)) #define cp pair<int,int> #define LL long long int using namespace std; const int maxn = 100005,maxm = 5000005; const LL INF = 1000000000000000001ll; inline LL read(){ LL out = 0,flag = 1
; char c = getchar(); while (c < 48 || c > 57){if (c == ‘-‘) flag = -1; c = getchar();} while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();} return out * flag; } int n,m; struct node{ int d,p,l; }e[maxn]; inline bool operator
<(const node& a,const node& b){ return a.d < b.d; } int Maxp; LL S[maxn],sum[maxm],val[maxm]; int ls[maxm],rs[maxm],cnt,rt[maxn]; void add(int& u,int pre,int l,int r,int pos,int v){ sum[u = ++cnt] = sum[pre]; val[u] = val[pre]; ls[u] = ls[pre]; rs[u] = rs[pre]; val[u] += 1ll * pos * v; sum[u] += v; if (l == r) return; int mid = l + r >> 1; if (mid >= pos) add(ls[u],ls[pre],l,mid,pos,v); else add(rs[u],rs[pre],mid + 1,r,pos,v); } LL query(int u,int v,int l,int r,LL ml){ if (!u) return 0; if (l == r) return ml * l; int mid = l + r >> 1; LL t = sum[ls[u]] - sum[ls[v]]; if (t >= ml) return query(ls[u],ls[v],l,mid,ml); return val[ls[u]] - val[ls[v]] + query(rs[u],rs[v],mid + 1,r,ml - t); } bool check(int d,LL g,LL L){ int pre = lower_bound(e + 1,e + 1 + n,(node){d,0,0}) - e - 1; if (S[n] - S[pre] < L) return false; return query(rt[n],rt[pre],1,Maxp,L) <= g; } int main(){ n = read(); m = read(); int M = 0; REP(i,n){ e[i].d = read(); e[i].p = read(); e[i].l = read(); M = max(M,e[i].d); Maxp = max(Maxp,e[i].p); } sort(e + 1,e + 1 + n); for (int i = 1; i <= n; i++) S[i] = S[i - 1] + e[i].l; for (int i = 1; i <= n; i++){ add(rt[i],rt[i - 1],1,Maxp,e[i].p,e[i].l); } LL g,L; while (m--){ g = read(); L = read(); int l = 1,r = M,mid; while (l < r){ mid = l + r + 1 >> 1; if (check(mid,g,L)) l = mid; else r = mid - 1; } if (check(l,g,L)) printf("%d\n",l); else puts("-1"); } return 0; }

BZOJ5343 [Ctsc2018]混合果汁 【二分 + 主席樹】