CTSC2018 Day2T1 Juice混合果汁

【题解】

  在考场上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 }
View Code
原文地址:https://www.cnblogs.com/DriverLao/p/9068142.html