1. 程式人生 > >luogu4602 混合果汁 (主席樹)

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 }