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;
    }
    
  • 相关阅读:
    《std测试》
    《关于cmp返回值的理解》
    《武汉大学2020年新生程序设计竞赛》
    《多校打卡 * 2018 Multi-University Training Contest 1》
    《牛客练习赛28-B》
    python使用sqlite示例
    python 使用mysql示例
    使用virtualenv为应用提供了隔离的Python运行环境
    生成字母验证码图片
    模拟微博登录
  • 原文地址:https://www.cnblogs.com/rainybunny/p/13455171.html
Copyright © 2011-2022 走看看