zoukankan      html  css  js  c++  java
  • Solution -「CTSC 2018」「洛谷 P4602」混合果汁

    (mathcal{Description})

      Link.

      (n) 种果汁,第 (i) 种美味度为 (d_i),每升价格 (p_i),一共 (l_i) 升。(m) 组询问,给定花费上限 (g) 和果汁需求量 (L),求混合多种果汁以满足要求时,所用果汁最小美味度的最大值。

      (n,m,p_ile10^5)

    (mathcal{Solution})

      最小值最大,显然二分。

      需要 check:能否用美味度不小于 (mid) 的果汁混合出 (L) 升,使得价格不超过 (g)

      没有美味度的限制,贪心地用单价更低的果汁就好啦!

      回归到原问题,以按美味度降序排列后的果汁编号为版本轴建主席树,树是以单价为下标的权值线段树。外层二分出 (mid),再在以 (mid) 为根的树上走,贪心地购买果汁(先买左子树,不够再去右子树)。

      就完了 qwq。复杂度 (mathcal O(nlog^2n))

    (mathcal{Code})

    #include <cstdio>
    #include <algorithm>
    
    const int MAXN = 1e5;
    int n, m, root[MAXN + 5];
    
    typedef long long LL;
    
    inline LL rint () {
    	LL x = 0; char s = getchar ();
    	for ( ; s < '0' || '9' < s; s = getchar () );
    	for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * 10 + ( s ^ '0' );
    	return x;
    }
    
    struct Juice {
    	int d, p, l;
    	inline void read () { d = rint (), p = rint (), l = rint (); }
    	inline bool operator < ( const Juice t ) const { return d > t.d; }
    } juice[MAXN + 5];
    
    struct PersistentSegmentTree {
    	static const int MAXND = MAXN * 40;
    	int cntnd, ch[MAXND + 5][2];
    	LL sum[MAXND + 5], prc[MAXND + 5];
    
    	inline void build ( int& rt, const int l, const int r ) {
    		rt = ++ cntnd;
    		if ( l == r ) return ;
    		int mid = l + r >> 1;
    		build ( ch[rt][0], l, mid ), build ( ch[rt][1], mid + 1, r );
    	}
    
    	inline void pushup ( const int rt ) {
    		sum[rt] = sum[ch[rt][0]] + sum[ch[rt][1]];
    		prc[rt] = prc[ch[rt][0]] + prc[ch[rt][1]];
    	}
    
    	inline void insert ( int& rt, const int l, const int r, const int p, const int v ) {
    		int old = rt, mid = l + r >> 1; rt = ++ cntnd;
    		ch[rt][0] = ch[old][0], ch[rt][1] = ch[old][1], sum[rt] = sum[old], prc[rt] = prc[old];
    		if ( l == r ) return sum[rt] += v, prc[rt] += 1ll * v * p, void ();
    		if ( p <= mid ) insert ( ch[rt][0], l, mid, p, v );
    		else insert ( ch[rt][1], mid + 1, r, p, v );
    		pushup ( rt );
    	}
    
    	inline LL buy ( const int rt, const int l, const int r, LL money, LL need ) {
    		if ( sum[rt] < need || money < 0 ) return -1;
    		if ( l == r ) return need * l <= money ? need * l : -1;
    		int mid = l + r >> 1;
    		if ( sum[ch[rt][0]] >= need ) return buy ( ch[rt][0], l, mid, money, need );
    		else {
    			LL t = buy ( ch[rt][1], mid + 1, r, money - prc[ch[rt][0]], need - sum[ch[rt][0]] );
    			return ~ t ? t + prc[ch[rt][0]] : -1;
    		}
    	}
    } pst;
    
    int main () {
    	n = rint (), m = rint ();
    	int mxp = 0;
    	for ( int i = 1; i <= n; ++ i ) {
    		juice[i].read ();
    		if ( mxp < juice[i].p ) mxp = juice[i].p;
    	}
    	std::sort ( juice + 1, juice + n + 1 );
    	pst.build ( root[0], 1, mxp );
    	for ( int i = 1; i <= n; ++ i ) {
    		pst.insert ( root[i] = root[i - 1], 1, mxp, juice[i].p, juice[i].l );
    	}
    	for ( LL g, L; m --; ) {
    		g = rint (), L = rint ();
    		int l = 1, r = n;
    		LL ans = -1, tmp;
    		while ( l <= r ) {
    			int mid = l + r >> 1;
    			if ( ~ pst.buy ( root[mid], 1, mxp, g, L ) ) r = ( ans = mid ) - 1;
    			else l = mid + 1;
    		}
    		printf ( "%d
    ", ~ ans ? juice[ans].d : -1 );
    	}
    	return 0;
    }
    
  • 相关阅读:
    PHP 开发 APP 接口 学习笔记与总结
    Java实现 LeetCode 43 字符串相乘
    Java实现 LeetCode 43 字符串相乘
    Java实现 LeetCode 43 字符串相乘
    Java实现 LeetCode 42 接雨水
    Java实现 LeetCode 42 接雨水
    Java实现 LeetCode 42 接雨水
    Java实现 LeetCode 41 缺失的第一个正数
    Java实现 LeetCode 41 缺失的第一个正数
    Java实现 LeetCode 41 缺失的第一个正数
  • 原文地址:https://www.cnblogs.com/rainybunny/p/13455171.html
Copyright © 2011-2022 走看看