zoukankan      html  css  js  c++  java
  • 【题解】[CTSC2018]混合果汁

    [CTSC2018]混合果汁

    ( ext{Solution:})

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

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

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

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

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

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

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

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

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

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

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

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

    这样,一个 (O(nlog nlog 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
    ",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
    ",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;
    }
    
  • 相关阅读:
    ScriptX实现的打印功能 只兼容IE
    JS 打印DIV
    C语言的代码内存布局
    二叉树
    C++中explicit关键字的作用
    基类和派生类
    C++ 输入输出流 总结
    python网络编程(六)---web客户端访问
    python 网络编程(五)---DNS域名系统
    python 网络编程(一)---基础
  • 原文地址:https://www.cnblogs.com/h-lka/p/14965276.html
Copyright © 2011-2022 走看看