【题解】
在考场上A掉的题。
把美味度排个序,然后按照价格p为权值建立主席树,把每个果汁按照拍好的顺序添加进去。主席树上维护总升数cnt以及总价格sum。对于每个询问,我们二分一个美味值,check的时候去主席树上查找大于等于这个美味值的果汁中购买L升的价格即可。
1 #include<cstdio> 2 #include<algorithm> 3 #define LL long long 4 #define rg register 5 #define N 100010 6 #define ls (a[u].l) 7 #define rs (a[u].r) 8 using namespace std; 9 int n,m,n2,tot,rt[N]; 10 LL cnt,sum,G,L; 11 struct rec{ 12 int d,p,l; 13 }jui[N]; 14 struct tree{ 15 LL cnt,sum; int l,r; 16 }a[2000010]; 17 inline LL read(){ 18 LL k=0; int f=1; char c=getchar(); 19 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 20 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 21 return k*f; 22 } 23 inline bool cmp(rec a,rec b){return a.d>b.d;} 24 void add(int &u,int l,int r,int pos){ 25 a[++tot]=a[u]; a[u=tot].cnt+=cnt; a[u].sum+=sum; 26 int mid=(l+r)>>1; 27 if(l<r) 28 if(pos<=mid) add(ls,l,mid,pos); 29 else add(rs,mid+1,r,pos); 30 } 31 LL query(int u,int l,int r,LL k){ 32 if(l==r) return a[u].cnt<k?G+1:k*l; 33 int mid=(l+r)>>1; 34 if(a[ls].cnt>=k) return query(ls,l,mid,k); 35 else return query(rs,mid+1,r,k-a[ls].cnt)+a[ls].sum; 36 } 37 int main(){ 38 n=read(); m=read(); 39 for(rg int i=1;i<=n;i++){ 40 jui[i].d=read(); jui[i].p=read(); jui[i].l=read(); 41 n2=max(n2,jui[i].p); 42 } 43 sort(jui+1,jui+1+n,cmp); 44 for(rg int i=1;i<=n;i++){ 45 cnt=jui[i].l; sum=1ll*cnt*jui[i].p; 46 add(rt[i]=rt[i-1],1,n2,jui[i].p); 47 } 48 while(m--){ 49 G=read(); L=read(); 50 int l=0,r=n+1; 51 while(l+1<r){ 52 int mid=(l+r)>>1; 53 if(query(rt[mid],1,n2,L)>G) l=mid; 54 else r=mid; 55 } 56 printf("%d ",r<=n?jui[r].d:-1); 57 } 58 return 0; 59 }