Educational Codeforces Round 167 (Rated for Div. 2) D(dp,贪心)

比赛地址

前言

这场比较容易,但是D没在考场上做出来。考场上一直在找规律求解 fi 数组,确没去想这是一个dp。第二天早上突然发现这题是dp。www。

A,B,C 太水了就不提了。

D

把这个问题简化为:给你 n 对关系,每对关系形如 (ai,aibi),意思是如果你现在手上的值 valvalai 那么可以使得 val=aibi 从而收获 2 的贡献。((使用条件,步长))然后会给你 m 个初始值 cj,求你可以获得的最大贡献。(每个初始值相互独立)

数据范围:1ai,bi1061cj109

由这个数据范围的特性容易想到先预处理 max{ai} 以内的,对于 cj>max{ai} 的,用贪心走最短的步长(获得最大的贡献)走到 <max{ai}

那么设 fi 表示初始值为 i 可以走的最大贡献。将 n 对关系放入一个桶数组,下标表示使用条件(ai,存最短的步长(min{aibi}(最有可能使得贡献值最大),在状态转移前同时更新当前可用最短步长(s,那么状态转移方程为:

f[i]=f[is]+1

最后统计答案,对于每个 cj:如果 cjmax{ai},那么直接累计 f[cj] 进入答案;如果 cj>max{ai},先减去若干倍(cnt)全局最小步长,得到一个最大的 k,使得 kmax{ai},那么对答案的贡献即 cnt+f[k]

时间复杂度 O(n)

Talk is cheap.Show me the code.

#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read() {
    int x = 0, f = 1; char ch = getchar();
    while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
    return x * f;
}
const int N = 1e6+7;
int n,m;
int a[N],b[N],f[N];
int t[N];
signed main()
{
	n = read(), m = read();
	int mx = 0;
	for(int i=1;i<=n;++i) a[i] = read(), mx = max(mx, a[i]);
	for(int i=1;i<=n;++i) b[i] = read();
	for(int i=1;i<=n;++i) {
		t[a[i]] = (!t[a[i]] ? a[i]-b[i] : min(t[a[i]], a[i]-b[i]));
	}
	int step = 0;
	for(int i=1;i<=mx;++i) {
		if(t[i]) step = (!step ? t[i] : min(step, t[i]));
		if(step) f[i] = f[i-step] + 1;
	}
	int ans = 0;
	while(m--) {
		int c = read();
		if(c > mx) {
			int d = step;
			int cnt = (c-mx-1)/d + 1;
			ans += cnt + f[c-cnt*d];
		} else {
			ans += f[c];
		}
	}
	printf("%lld\n",ans*2);
	return 0;
}
posted @   基地AI  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示