[bzoj 5343][CTSC2018]混合果汁

传送门

Description

商店里有 (n) 种果汁,编号为 (0,1,cdots,n-1)(i) 号果汁的美味度是 (d_i),每升价格为 (p_i)。小 R 在制作混合果汁时,还有一些特殊的规定,即在一瓶混合果汁中,(i)号果汁最多只能添加 (l_i)升。

现在有 (m) 个小朋友过来找小 R 要混合果汁喝,他们都希望小 R 用商店里的果汁制作成一瓶混合果汁。其中,第 (j)个小朋友希望他得到的混合果汁总价格不大于 (g_j),体积不小于 (L_j)。在上述这些限制条件下,小朋友们还希望混合果汁的美味度尽可能地高,一瓶混合果汁的美味度等于所有参与混合的果汁的美味度的最小值。请你计算每个小朋友能喝到的最美味的混合果汁的美味度。

Solution

整体二分?

开个线段树存当前价格区间能有多少升的果汁以及它们的总价格

对于一个价格(g)直接在线段树上二分最多能买多少升果汁


Code 

#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return x*f;
}
#define MN 100005
#define N 100000
int n,m,ans[MN];
struct juice{
	ll d,p,l;
	bool operator<(const juice &o)const{return d<o.d;}
}J[MN];
struct ques{ll g,l;int id;}q[MN],tmp[MN];
ll T[MN<<2],P[MN<<2];
#define mid ((l+r)>>1)
inline void pushup(int x){T[x]=T[x<<1]+T[x<<1|1];P[x]=P[x<<1]+P[x<<1|1];}
void Modify(int x,int l,int r,ll p,ll L)
{
	if(l==r) return (void)(T[x]+=L,P[x]+=1ll*p*L);
	p<=mid?Modify(x<<1,l,mid,p,L):Modify(x<<1|1,mid+1,r,p,L);
	pushup(x);
}
ll Query(int x,int l,int r,ll g)
{
	if(l==r)
	{
		if(l==0) return T[x];
		return min(T[x],g/l);
	}
	if(g>=P[x<<1]) return T[x<<1]+Query(x<<1|1,mid+1,r,g-P[x<<1]);
	else return Query(x<<1,l,mid,g);
}
void solve(int l,int r,int ql,int qr)
{
	if(l>r||ql>qr) return;
	register int i;
	if(l==r)
	{
		for(i=ql;i<=qr;++i) ans[q[i].id]=J[l].d;
		return;
	}
	register int Mid=(l+r)>>1,lcnt=ql,rcnt=qr;
	for(i=l;i<=Mid;++i) Modify(1,0,N,J[i].p,-J[i].l);
	for(i=ql;i<=qr;++i) Query(1,0,N,q[i].g)>=q[i].l?tmp[rcnt--]=q[i]:tmp[lcnt++]=q[i];
	for(i=ql;i<=qr;++i) q[i]=tmp[i];
	solve(Mid+1,r,rcnt+1,qr);
	for(i=l;i<=Mid;++i) Modify(1,0,N,J[i].p,J[i].l);
	solve(l,Mid,ql,lcnt-1);
}
int main()
{
	n=read();m=read();
	register int i;
	for(i=1;i<=n;++i) J[i].d=read(),J[i].p=read(),J[i].l=read();
	J[++n].d=-1;J[n].p=0;J[n].l=1e18;
	for(i=1;i<=m;++i) q[i].g=read(),q[i].l=read(),q[i].id=i;
	std::sort(J+1,J+n+1);
	for(i=1;i<=n;++i) Modify(1,0,N,J[i].p,J[i].l);
	solve(1,n,1,m);
	for(i=1;i<=m;++i) printf("%d
",ans[i]);
	return 0;
}


Blog来自PaperCloud,未经允许,请勿转载,TKS!

原文地址:https://www.cnblogs.com/PaperCloud/p/10281748.html