【BZOJ】5343: [Ctsc2018]混合果汁 主席樹&二分
阿新 • • 發佈:2018-12-11
題解
可以二分一個答案,每次貪心從美味度的最小的選起(儘可能地選更大體積的飲料),所以最優選擇方案也是固定的。可以按建主席樹。二分查詢即可。
程式碼
#include<bits/stdc++.h>
#define RI register
#define gc getchar()
#define si isdigit(ch)
#define lc(k) t[(k)].ch[0]
#define rc(k) t[(k)].ch[1]
#define mid (((l)+(r))>>1)
using namespace std;
const int N=1e5+10;
typedef long long ll;
int n,m,cs,P[2],D[N];
ll G,V;
int cnt,rt[N];
struct juice{
int d,p,l;
bool operator <(const juice&ky)const{
return d<ky.d;
}
}drk[N];
struct node{
int ch[2];ll sv,sc;
node(){};
node(int sonl,int sonr,ll sv_,ll sc_){ch[0]=sonl;ch[1]=sonr; sv=sv_;sc=sc_;}
}t[N*33];
char ch;
template<class T>
inline void rd(T &x)
{
ch=gc;x=0;
for(;!si;ch=gc);
for(;si;ch=gc) x=x*10+(ch^48);
}
inline void ins(int pre,int &k,int l,int r,int pos,int vv)
{
if(k==pre) t[(k=++cnt)]=node(lc(pre),rc(pre),t[pre].sv,t[pre].sc);
t[k].sv+=vv;t[k] .sc+=1ll*pos*vv;
if(l==r) return;
if(pos<=mid) ins(lc(pre),lc(k),l,mid,pos,vv);
else ins(rc(pre),rc(k),mid+1,r,pos,vv);
}
inline ll query(int pre,int k,int l,int r,ll res)
{
if(!k) return 0;
if(l==r) return min(res/l,t[k].sv-t[pre].sv);
ll sum=t[lc(k)].sc-t[lc(pre)].sc;
if(res<=sum) return query(lc(pre),lc(k),l,mid,res);
return t[lc(k)].sv-t[lc(pre)].sv+query(rc(pre),rc(k),mid+1,r,res-sum);
}
int main(){
RI int i,j,l,r,ans;
rd(n);rd(m);P[0]=N;
for(i=1;i<=n;++i){
rd(drk[i].d),rd(drk[i].p),rd(drk[i].l);
P[0]=min(P[0],drk[i].p);P[1]=max(P[1],drk[i].p);
}
sort(drk+1,drk+n+1);
D[(cs=1)]=drk[1].d;
for(i=1;i<=n;++i){
if(D[cs]!=drk[i].d){D[++cs]=drk[i].d;rt[cs]=rt[cs-1];}
ins(rt[cs-1],rt[cs],P[0],P[1],drk[i].p,drk[i].l);
}
for(;m;--m){
rd(G);rd(V);
l=1;r=cs;ans=-1;
for(;l<=r;){
if(query(rt[mid-1],rt[cs],P[0],P[1],G)>=V){
ans=D[mid];l=mid+1;
}else r=mid-1;
}
printf("%d\n",ans);
}
return 0;
}