zoukankan      html  css  js  c++  java
  • [洛谷P4602] CTSC2018 混合果汁

    问题描述

    小 R 热衷于做黑暗料理,尤其是混合果汁。 商店里有 n 种果汁,编号为 0, 1, 2, . . . , n − 1。i 号果汁的美味度是 di,每升价格为 pi。小 R 在制作混合果汁时,还有一些特殊的规定,即在一瓶混合果汁中,i 号果汁最 多只能添加 li 升。 现在有 m 个小朋友过来找小 R 要混合果汁喝,他们都希望小 R 用商店里的果汁 制作成一瓶混合果汁。其中,第 j 个小朋友希望他得到的混合果汁总价格不大于 gj,体 积不小于 Lj。在上述这些限制条件下,小朋友们还希望混合果汁的美味度尽可能地高, 一瓶混合果汁的美味度等于所有参与混合的果汁的美味度的最小值。请你计算每个小 朋友能喝到的最美味的混合果汁的美味度。

    输入格式

    从文件 juice.in 中读入数据。

    输入第一行包含两个正整数 n, m,表示果汁的种数和小朋友的数量。

    接下来 n 行,每行三个正整数 di , pi , li,表示 i 号果汁的美味度为 di,每升价格为 pi,在一瓶果汁中的添加上限为 li。

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

    输出格式

    输出到文件 juice.out 中。

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

    样例输入

    3 4
    1 3 5
    2 1 3
    3 2 5
    6 3
    5 3
    10 10
    20 10

    样例输出

    3
    2
    -1
    1

    说明

    对于所有的测试数据,保证 n, m ≤ 100000,1 ≤ di , pi , li ≤ 10^5,1 ≤ gj , Lj ≤ 10^18。

    解析

    通过打表等一系列玄学方式可以发现答案具有单调性。二分一个d,则我们只能选择大于等于d的果汁。然后对所有大于等于d的果汁建立一棵以价格为下标的权值线段树,每个节点还要保存一下总体积和价格。这样我们就可以在权值线段树上用Lim二分了。

    但是不能每二分一次就重新建树。我们可以建立一棵主席树利用可持久化来解决这个问题。

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define int long long
    #define N 100002
    #define T 100000
    using namespace std;
    struct ChairmanTree{
    	int l,r,suml,sump;
    }t[N*40];
    struct juice{
    	int d,p,l;
    }a[N];
    int n,m,i,g[N],L[N],root[N],p;
    int read()
    {
    	char c=getchar();
    	int w=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c<='9'&&c>='0'){
    		w=w*10+c-'0';
    		c=getchar();
    	}
    	return w;
    }
    int my_comp(const juice &x,const juice &y)
    {
    	return x.d<y.d;
    }
    int insert(int pre,int l,int r,int L,int P)
    {
    	p++;
    	int num=p;
    	t[p]=t[pre];
    	t[p].suml+=L;t[p].sump+=L*P;
    	if(l<r){
    		int mid=(l+r)/2;
    		if(P<=mid) t[p].l=insert(t[pre].l,l,mid,L,P);
    		else t[p].r=insert(t[pre].r,mid+1,r,L,P);
    	}
    	return num;
    }
    int ask(int p,int l,int r,int L)
    {
    	if(l==r) return l*L;
    	int mid=(l+r)/2;
    	if(L<=t[t[p].l].suml) return ask(t[p].l,l,mid,L);
    	return t[t[p].l].sump+ask(t[p].r,mid+1,r,L-t[t[p].l].suml);
    }
    signed main()
    {
    	n=read();m=read();
    	for(i=1;i<=n;i++) a[i].d=read(),a[i].p=read(),a[i].l=read();
    	for(i=1;i<=m;i++) g[i]=read(),L[i]=read();
    	a[0].d=-1;
    	sort(a+1,a+n+1,my_comp);
    	for(i=n;i>=1;i--) root[i]=insert(root[i+1],1,T,a[i].l,a[i].p);
    	for(i=1;i<=m;i++){
    		int l=1,r=T,mid,ans=0;
    		while(l<=r){
    			mid=(l+r)/2;
    			if(L[i]<=t[root[mid]].suml&&ask(root[mid],1,T,L[i])<=g[i]){
    				ans=mid;
    				l=mid+1;
    			}
    			else r=mid-1;
    		}
    		printf("%lld
    ",a[ans].d);
    	}
    	return 0;
    }
    
  • 相关阅读:
    A1066 Root of AVL Tree (25 分)
    A1099 Build A Binary Search Tree (30 分)
    A1043 Is It a Binary Search Tree (25 分) ——PA, 24/25, 先记录思路
    A1079; A1090; A1004:一般树遍历
    A1053 Path of Equal Weight (30 分)
    A1086 Tree Traversals Again (25 分)
    A1020 Tree Traversals (25 分)
    A1091 Acute Stroke (30 分)
    A1103 Integer Factorization (30 分)
    A1032 Sharing (25 分)
  • 原文地址:https://www.cnblogs.com/LSlzf/p/11878957.html
Copyright © 2011-2022 走看看