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;
    }
    
  • 相关阅读:
    Leetcode 15 3Sum
    Leetcode 383 Ransom Note
    用i个点组成高度为不超过j的二叉树的数量。
    配对问题 小于10 1.3.5
    字符矩阵的旋转 镜面对称 1.2.2
    字符串统计 连续的某个字符的数量 1.1.4
    USACO twofive 没理解
    1002 All Roads Lead to Rome
    USACO 5.5.1 求矩形并的周长
    USACO 5.5.2 字符串的最小表示法
  • 原文地址:https://www.cnblogs.com/h-lka/p/14965276.html
Copyright © 2011-2022 走看看