码迷,mamicode.com
首页 > 其他好文 > 详细

【题解】[CTSC2018]混合果汁

时间:2021-07-05 17:22:16      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:细节   def   inf   math   targe   been   problem   mit   tar   

[CTSC2018]混合果汁

\(\text{Solution:}\)

题目有三个限制:饮料体积的限制、要求的饮料总体积限制、总价格限制。

首先,美味度最大是我们一定要满足的条件。考虑如何让它变得好维护:

将饮料按照美味度排序,并按顺序建立主席树。

这样,\(root_i\) 所对应的区间 \([1,i]\) 一定是一个美味度递减的区间。这样它就有了单调性。

那么,对于体积和价格的限制咋办呢?

首先,贪心地,价格绝对越小越好。所以,将主席树用来维护下标为价格的值域树。

那么,上面维护啥呢?还剩下一个体积没有考虑,那么我们可以考虑维护体积。

所以,树上维护:到当前点从最便宜的开始能买到多少升饮料,以及需要花费的钱。

那么,考虑每次二分一个答案,由于它具有单调性。

那么我们就可以在树上二分了:在满足体积限制下同时使价格最小。

线段树上二分要注意细节:有可能将所有饮料买完也不够喝;同时如果一个饮料卖不完,观察到这种情况一定出现在叶子。

所以到最后处理即可。如果要递归右区间,记得加上买左区间的钱。

这样,一个 \(O(n\log n\log v)\) 的算法就出来了。还是在线的。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN=5e5+10;
const int INF=1e5+10;
int rt[INF],n,m;
struct T{int ls,sum,rs,sumv;}tr[MAXN<<5];
struct dk{int d,p,l;}q[INF];
int node;
inline int read() {
	int s=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)) {
		if(ch==‘-‘)w=-1;
		ch=getchar();
	}
	while(isdigit(ch)) {
		s=s*10-48+ch;
		ch=getchar();
	}
	return w*s;
}
int change(int x,int l,int r,int pos,int v){
	int p=++node;
	tr[p]=tr[x];
	tr[p].sum+=pos*v;
	tr[p].sumv+=v;
	if(l==r)return p;
	int mid=(l+r)>>1;
	if(pos<=mid)tr[p].ls=change(tr[p].ls,l,mid,pos,v);
	else tr[p].rs=change(tr[p].rs,mid+1,r,pos,v);
	return p;
}
bool flag;
int query_V(int x,int L,int R,int v){
	int mid=(L+R)>>1;
	if(L==R) {
		if(v>tr[x].sumv) flag=1;
		return v*L;
	}
	if(v<=tr[tr[x].ls].sumv)return query_V(tr[x].ls,L,mid,v);
	return query_V(tr[x].rs,mid+1,R,v-tr[tr[x].ls].sumv)+tr[tr[x].ls].sum;
}
void solve(int c,int v){
//	c->prive
//	v->volume
//	Tree was built in c,and should follow the limit of the volume
//	consider checking answer:try to guess a delicious_percent,then we should check if is is can be got.
//	In the Tree,We have known the least price of this situation.
//	We should get the information of the price and volume through this tree.
//	Make sure:(Nowprice,Max) we can get sumv and sum(V and price.)
//	then we first consider volume.Price has been known and it is decrease.
//	we just need get the left position which sumv>V.
//	and check the answer.
//	int L=1,R=n,ans=-1;
//	while(L<=R){
//		int mid=(L+R)>>1;
//		if(check(mid,v,c))ans=mid,R=mid-1;
//		else L=mid+1;
//	}
//	printf("%d\n",ans);
	int L=1,R=n,ans=-1,qv=0;
	while(L<=R){
		int mid=(L+R)>>1;flag=0;
		qv=query_V(rt[mid],1,INF,v);
		if(qv>c||flag)L=mid+1;
		else ans=mid,R=mid-1;
	}
	
	ans!=-1?printf("%lld\n",q[ans].d):puts("-1");
}
inline bool cmp(dk a,dk b){return a.d==b.d?a.p<b.p:a.d>b.d;}
signed main(){
	n=read();m=read();
	for(int i=1;i<=n;++i)q[i].d=read(),q[i].p=read(),q[i].l=read();
	sort(q+1,q+n+1,cmp);
	for(int i=1;i<=n;++i)rt[i]=change(rt[i-1],1,INF,q[i].p,q[i].l);
	for(int i=1;i<=m;++i){
		int gi=read(),Li=read();
		solve(gi,Li);
	}
	return 0;
}

【题解】[CTSC2018]混合果汁

标签:细节   def   inf   math   targe   been   problem   mit   tar   

原文地址:https://www.cnblogs.com/h-lka/p/14965276.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有
迷上了代码!