[bzoj5343][loj2555]: [Ctsc2018]混合果汁 (二分答案+主席树)

www.cnblogs.com/shaokele/


p1
p2
p3

题目地址:  [loj2555]: [Ctsc2018]混合果汁

题目大意:   题目很简洁了:)####

  

题解:

  二分答案,用主席树维护贪心操作
  
  先按 (d) 排序,二分 (ans) **
  
  
主席树操作判断是否符合**
  
  细节注意
  


AC代码

#include <cstdio> 
#include <algorithm>
#define ll long long
using namespace std;
const int N=1e5+5,M=1800005;
int n,Q,sz,mxd,mxp;
int ls[M],rs[M],root[M];
ll g,L;
ll s[N],sum[M],val[M];
inline ll read(){	
	ll x=0;int f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
struct node{
		int d,p,l;
}A[N];
bool operator < (const node &a,const node &b){
		return a.d<b.d; 
}
void insert(int l,int r,int &u,int pre,int p,int L){
	u=++sz;
	sum[u]=sum[pre];val[u]=val[pre];
	ls[u]=ls[pre];rs[u]=rs[pre];
	sum[u]+=L;val[u]+=1ll*p*L;
	if(l==r)return;
	int mid=(l+r)>>1;
	if(p<=mid)insert(l,mid,ls[u],ls[pre],p,L);
	else insert(mid+1,r,rs[u],rs[pre],p,L);
}
ll ask(int l,int r,int u,int pre,ll L){
	if(!u)return 0;
	if(l==r)return L*l;
	int mid=(l+r)>>1;
	ll tmp=sum[ls[u]]-sum[ls[pre]];
	if(tmp>=L)return ask(l,mid,ls[u],ls[pre],L);
	else return val[ls[u]]-val[ls[pre]]+ask(mid+1,r,rs[u],rs[pre],L-tmp);
}
bool check(int mid,ll g,ll L){
	int pre=lower_bound(A+1,A+n+1,(node){mid,0,0})-A-1;
	if(s[n]-s[pre]<L)return 0;
	else return ask(1,mxp,root[n],root[pre],L)<=g;
}
int main(){
	n=read(),Q=read();
	for(int i=1;i<=n;i++){
		A[i].d=read(),A[i].p=read(),A[i].l=read();
		mxd=max(mxd,A[i].d);
		mxp=max(mxp,A[i].p);
	}
	sort(A+1,A+n+1);
	for(int i=1;i<=n;i++)
		s[i]=s[i-1]+A[i].l;
	for(int i=1;i<=n;i++)
		insert(1,mxp,root[i],root[i-1],A[i].p,A[i].l);
	while(Q--){
		g=read(),L=read();
		int l=1,r=mxd,ans=-1;
		while(l<=r){
			int mid=(l+r)/2;
			if(check(mid,g,L)){
				ans=mid;
				l=mid+1;
			}else r=mid-1;
		}
		printf("%d
",ans);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/shaokele/p/9109071.html