zoukankan      html  css  js  c++  java
  • [Bzoj]5343: [Ctsc2018]混合果汁

    5343: [Ctsc2018]混合果汁


    题目描述

    小 R 热衷于做黑暗料理,尤其是混合果汁。

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

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

    输入输出格式

    输入格式:

    输入第一行包含两个正整数 (n, m),表示果汁的种数和小朋友的数量。接下来 (n) 行,每行三个正整数 (d_i, p_i, l_i),表示 (i) 号果汁的美味度为 (d_i),每升价格为(p_i),在一瓶果汁中的添加上限为 (l_i)

    接下来 (m) 行依次描述所有小朋友:每行两个数正整数 (g_j, L_j)描述一个小朋友,表示他最多能支付 (g_j) 元钱,他想要至少 (L_j) 升果汁。

    输出格式:

    对于所有小朋友依次输出:对于每个小朋友,输出一行,包含一个整数,表示他能喝到的最美味的混合果汁的美味度。如果无法满足他的需求,则输出 (-1)

    说明

    对于所有的测试数据,保证 (n, m le 100000)(1 le d_i,p_i,l_i le 10^5, 1 le g_j, L_j le 10^{18})

    测试点编号 (n=) (m=) 其他限制
    1,2,3 (10) (10)
    4,5,6 (500) (500)
    7,8,9 (5000) (5000)
    10,11,12 (100000) (100000) (p_i=1)
    13,14,15 (100000) (100000) (l_i=1)
    16,17,18,19,20 (100000) (100000)

    题目分析:

    考虑大暴力。

    假设枚举所有的(d),可以发现从大到小答案是单调的。

    那么我们先按照(d)排一遍序,然后二分这个(d),对于每个d直接暴力寻找是否可以满足条件,不难发现这个算法复杂度是(O(n^2log^2n))的。

    思考如何优化掉一个(n),发现可以对价格建立一棵权值线段树,然后对于二分的(d)就查询当前的状态是否能够满足总价格小于(g),发现这个(d)是可持久化的,可以用主席树实现。

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN=1e5+7;
    #define ll long long
    #define mid ((l+r>>1))
    struct Node{
    	int d,p,l;
    	bool operator <(const Node &rhs)const{return d<rhs.d;}
    }a[MAXN];
    struct Segtree{
    	ll v,w;
    }st[MAXN<<5];
    int L[MAXN<<5],R[MAXN<<5],T[MAXN],size;
    int n,m;
    ll g,lim;
    inline ll read()
    {
        ll x=0,c=1;char ch=' ';
        while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
        while(ch=='-') c*=-1,ch=getchar();
        while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return c*x;
    }
    int update(int pre,int l,int r,int x,int v,ll w)
    {
    	int rt=++size;
    	L[rt]=L[pre],R[rt]=R[pre],st[rt].v=st[pre].v+v,st[rt].w=st[pre].w+w;
    	if(l==r) return rt;
    	if(x<=mid) L[rt]=update(L[pre],l,mid,x,v,w);
    	else R[rt]=update(R[pre],mid+1,r,x,v,w);
    	return rt;
    }
    ll query(int v,int l,int r,ll x)
    {
    	if(l==r) return (ll)x*l;
    	if(st[L[v]].v>=x) return query(L[v],l,mid,x);
    	else return st[L[v]].w+query(R[v],mid+1,r,x-st[L[v]].v);
    }
    ll solve()
    {
    	g=read();lim=read();
    	if(lim>g) return -1;
    	int l=0,r=n,ans=0;
    	while(l<=r){
    		ll Mid=l+r>>1;
    		ll d=query(T[Mid],1,MAXN,lim);
    		if(lim<=st[T[Mid]].v&&d<=g) ans=Mid,l=Mid+1;
    		else r=Mid-1;
    	}
    	return a[ans].d;
    }
    int main()
    {
    //	freopen("data.in","r",stdin);
    //	freopen("my.out","w",stdout);
    	n=read();m=read();
    	for(int i=1;i<=n;i++){
    		a[i].d=read();a[i].p=read();a[i].l=read();
    	}
    	sort(a+1,a+n+1);
    	a[0].d=-1;
    	T[n+1]=++size;
    	for(int i=n;i>=1;i--){
    		T[i]=update(T[i+1],1,MAXN,a[i].p,a[i].l,(ll)a[i].l*a[i].p);
    	}
    	T[0]=T[1];
    	while(m--)	printf("%lld
    ",solve());
    	return 0;
    }
    
  • 相关阅读:
    简易高重用的jdbcutils工具封装实现类以及简易连接池实现
    http header 具体解释
    zoj 3888 Twelves Monkeys 二分+线段树维护次小值
    hyperLink的定制
    document.body.clientHeight的取值
    在循环中创建网页元素的问题
    mongo db 启动停止
    myeclipse 2014破解
    weblogic 集群部署时上传jsp不更新问题
    Spring classPath:用法
  • 原文地址:https://www.cnblogs.com/victorique/p/10113602.html
Copyright © 2011-2022 走看看