#P3459. 第1题-收集晶体
-
ID: 2801
Tried: 58
Accepted: 25
Difficulty: 3
所属公司 :
米哈游
时间 :2025年8月24日
-
算法标签>前缀和
第1题-收集晶体
思路
-
设前缀和 Ai=∑j=1iaj、Bi=∑j=1ibj。
-
单次遍历,逐日更新前缀:在第 i 天先计算 di=max(0,ai−bi)。若 di>0,比较“包含当天”的前缀 Bi 与 Ai:
- 若 Bi≥Ai,加 di;否则加 2di。
-
时间复杂度 O(n),空间 O(1)。用 64 位整型累计答案与前缀和。
C++
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
if (!(cin >> n)) return 0;
vector<long long> a(n), b(n);
for (int i = 0; i < n; ++i) cin >> a[i];
for (int i = 0; i < n; ++i) cin >> b[i];
long long sa = 0, sb = 0; // 到前一天为止的前缀和
long long ans = 0;
for (int i = 0; i < n; ++i) {
long long need = a[i], got = b[i];
long long di = need > got ? (need - got) : 0; // 当天缺口
long long Ai = sa + need; // 包含当天后的 A_i
long long Bi = sb + got; // 包含当天后的 B_i
if (di > 0) {
if (Bi >= Ai) ans += di;
else ans += 2 * di;
}
sa = Ai;
sb = Bi;
}
cout << ans << "\n";
return 0;
}
Python
import sys
def main():
data = sys.stdin.read().strip().split()
if not data:
return
it = iter(data)
n = int(next(it))
a = [int(next(it)) for _ in range(n)]
b = [int(next(it)) for _ in range(n)]
sa = 0 # 到前一天为止的 A 前缀
sb = 0 # 到前一天为止的 B 前缀
ans = 0
for i in range(n):
need = a[i]
got = b[i]
di = max(0, need - got) # 当天缺口
Ai = sa + need # 包含当天后的 A_i
Bi = sb + got # 包含当天后的 B_i
if di > 0:
ans += di if Bi >= Ai else 2 * di
sa = Ai
sb = Bi
print(ans)
if __name__ == "__main__":
main()
Java
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
FastScanner fs = new FastScanner(System.in);
int n = fs.nextInt();
long[] a = new long[n];
long[] b = new long[n];
for (int i = 0; i < n; i++) a[i] = fs.nextLong();
for (int i = 0; i < n; i++) b[i] = fs.nextLong();
long sa = 0L; // 到前一天为止的 A 前缀
long sb = 0L; // 到前一天为止的 B 前缀
long ans = 0L;
for (int i = 0; i < n; i++) {
long need = a[i], got = b[i];
long di = Math.max(0L, need - got); // 当天缺口
long Ai = sa + need; // 包含当天后的 A_i
long Bi = sb + got; // 包含当天后的 B_i
if (di > 0) {
ans += (Bi >= Ai) ? di : 2L * di;
}
sa = Ai;
sb = Bi;
}
System.out.println(ans);
}
// 简易快读
static final class FastScanner {
private final InputStream in;
private final byte[] buffer = new byte[1 << 16];
private int ptr = 0, len = 0;
FastScanner(InputStream is) { in = is; }
private int read() throws IOException {
题目内容
在一段史诗般的冒险游戏中,米小游制定了 n 天的任务计划,其中第 i 天目标是收集 ai 个魔法晶体;然而,实际第 i 天他收集了 bi 个晶体。
为了平衡游戏难度,系统设定如下惩罚机制:
-
如果第 i 天 bi<ai ;且到第 i 天为止的累计实际收集总量不少于累计目标总量,则需要额外消耗 ai−bi 个能量点;
-
如果第 i 天 bi<ai ,且到第 i 天为止的累计实际收集总量小于累计目标总量,则需要额外消耗 2×(ai−bi) 个能量点;
请计算米小游总共需要额外消耗多少个能量点,以完成整个冒险。
输入描述
第一行输入一个整数 n(1≦n≦2×105) ,表示冒险天数。
第二行输入 n 个整数 a1,a2,...,an(1≦ai≦109) ,表示每天的目标晶体数。
第二行输入 n 个整数 b1,b2,...,bn(1≦bi≦109) ,表示每天的实际晶体数。
输出描述
输出一个整数,表示总额外消耗的能量点数。
样例1
输入
3
2 1 3
1 2 2
输出
4
样例2
输入
5
3 3 3 3 3
2 4 1 5 2
输出
8