Live2D

Solution -「AGC 034C」Tests

Description

  Link.

  给定非负整数序列 {ln},{rn},{bn},X,求最小的 s,使得存在非负整数序列 {an},{cn},满足 aiXi=1nai=sci[li,ri],且

i=1nci(aibi)0

  所有输入均 105

Solution

  显然二分 s,仅需做到检测某个 s 是否合法。下令 w=i=1nciai

  假设 {an} 已经确定,那么所有满足 aibici=ri,其余 ci=li。考虑初始时所有 ai=0,ci=li,现在把 s1 挨个加到一些 ai 上。当 ai<bi 时,对 w 贡献 li(此时 ci 仍取 li);当 ai=bi 时,对 w 贡献由 li 转为 rici 变成 ri);继续增加,对 w 贡献 ri。最终仅需比较 wi=1nlibi 的大小。

  所以问题抽象为:有 n 个分段函数 f1..n(x),满足

fi(x)={lixx[0,bi]Nlibi+ri(xbi)x(bi,X]N

  仅需钦定 {xn},使得 i=1nfi(xi) 取最大。

  考虑贪心,不难证明:至多有一个 0<xi<X。直接枚举哪一个 0<xi<X,贪心地选取最大的 fi(X),即可 O(n) 检测。最终复杂度 O(nlogi=1nbi)

Code

/* Clearink */

#include <cstdio>
#include <algorithm>

#define rep( i, l, r ) for ( int i = l, repEnd##i = r; i <= repEnd##i; ++i )
#define per( i, r, l ) for ( int i = r, repEnd##i = l; i >= repEnd##i; --i )

inline int rint () {
	int x = 0, f = 1; char s = getchar ();
	for ( ; s < '0' || '9' < s; s = getchar () ) f = s == '-' ? -f : f;
	for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * 10 + ( s ^ '0' );
	return x * f;
}

typedef long long LL;

const int MAXN = 1e5;
int n, x, b[MAXN + 5], l[MAXN + 5], r[MAXN + 5], ord[MAXN + 5];
LL full[MAXN + 5];

inline LL contr ( const int i, const int s ) {
	return s <= b[i] ? 1ll * s * l[i]
		: 1ll * l[i] * b[i] + 1ll * ( s - b[i] ) * r[i];
}

inline void init () {
	std::sort ( ord + 1, ord + n + 1, []( const int i, const int j ) {
		return contr ( i, x ) > contr ( j, x );
	} );
	rep ( i, 1, n ) full[i] = full[i - 1] + contr ( ord[i], x );
}

inline LL calc ( const LL scr ) {
	/*
	 * let's come up with a greedy algorithm!
	 * */
	int fcnt = scr / x, rest = scr % x;
	LL ret = 0;
	rep ( i, 1, n ) { // score on exam <ord[i]> is <rest>.
		LL cur = contr ( ord[i], rest );
		if ( i > fcnt ) cur += full[fcnt];
		else cur += full[fcnt + 1] - contr ( ord[i], x );
		ret = cur > ret ? cur : ret;
	}
	return ret;
}

int main () {
	n = rint (), x = rint ();
	LL sum = 0, sb = 0;
	rep ( i, 1, n ) {
		ord[i] = i;
		b[i] = rint (), l[i] = rint (), r[i] = rint ();
		sum += 1ll * b[i] * l[i], sb += b[i];
	}
	init ();
	LL lef = 0, rig = sb;
	while ( lef < rig ) {
		LL mid = lef + rig >> 1;
		if ( calc ( mid ) >= sum ) rig = mid;
		else lef = mid + 1;
	}
	printf ( "%lld\n", lef );
	return 0;
}

posted @   Rainybunny  阅读(137)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示