luogu4602 混合果汁 (主席树)

按照美味值从大到小排序,对于每个询问,我想二分找到一个前缀来满足条件

那么以单价为下标建主席树,维护区间的最大体积和 以及满足这个最大体积需要的价钱

然后二分答案,再在主席树上二分,找到恰好满足的那个位置(肯定是单价越小越好)

复杂度$O(nlog^2n)$

 1 #include<bits/stdc++.h>
 2 #define CLR(a,x) memset(a,x,sizeof(a))
 3 #define MP make_pair
 4 using namespace std;
 5 typedef long long ll;
 6 typedef unsigned long long ull;
 7 typedef pair<int,int> pa;
 8 const int maxn=1e5+10,maxp=4e6+10;
 9 
10 inline ll rd(){
11     ll x=0;char c=getchar();int neg=1;
12     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
13     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
14     return x*neg;
15 }
16 
17 struct Juice{
18     int l,d,p;
19 }jui[maxn];
20 int N,M,rt[maxn];
21 int ch[maxp][2],pct;
22 ll suml[maxp],sumv[maxp];
23 
24 inline bool cmp(Juice a,Juice b){return a.d>b.d;}
25 
26 inline void add(int pre,int &p,int l,int r,int x,int y){
27     p=++pct;
28     suml[p]=suml[pre]+y,sumv[p]=sumv[pre]+1ll*y*x;
29     if(l<r){
30         int m=l+r>>1;
31         if(x<=m) ch[p][1]=ch[pre][1],add(ch[pre][0],ch[p][0],l,m,x,y);
32         else ch[p][0]=ch[pre][0],add(ch[pre][1],ch[p][1],m+1,r,x,y);
33     }
34 }
35 
36 inline bool judge(int p,int l,int r,ll g,ll v){
37     int m=l+r>>1;
38     // printf("~%d %d\n",l,r);
39     if(l==r){
40         if(suml[p]>=v) return l*v<=g;
41         else return 0;
42     }
43     int a=ch[p][0];
44     if(suml[a]<v){
45         v-=suml[a],g-=sumv[a];
46         if(g<=0) return 0;
47         return judge(ch[p][1],m+1,r,g,v);
48     }else{
49         return judge(ch[p][0],l,m,g,v);
50     }
51 }
52 
53 int main(){
54     //freopen("","r",stdin);
55     int i,j,k;
56     N=rd(),M=rd();
57     for(i=1;i<=N;i++){
58         jui[i].d=rd(),jui[i].p=rd(),jui[i].l=rd();
59     }sort(jui+1,jui+N+1,cmp); 
60     for(i=1;i<=N;i++) add(rt[i-1],rt[i],1,1e5,jui[i].p,jui[i].l);
61     jui[N+1].d=-1;
62     for(i=1;i<=M;i++){
63         ll g=rd(),v=rd();
64         int l=1,r=N+1,ans=N+1;
65         while(l<=r){
66             int m=l+r>>1;
67             if(judge(rt[m],1,1e5,g,v)) ans=m,r=m-1;
68             else l=m+1;
69         }
70         printf("%d\n",jui[ans].d);
71     }
72     return 0;
73 }

 

posted @ 2018-12-01 18:46  Ressed  阅读(119)  评论(0编辑  收藏  举报