1 条题解
-
0
「PA 2020」Elektrownie i fabryki 题解
算法思路
本题使用动态规划结合树状数组优化来解决电网连接问题。核心思想是通过维护前缀和的最优解来找到最小连接成本。
关键观察
1. 问题转化
电网连接问题可以转化为:
- 需要确保每个工厂都能连接到某个发电厂
- 总电力供应要满足总需求:
- 最小化连接线路总长度
2. 前缀和性质
定义前缀和 ,则:
- 是问题有解的必要条件
- 对于位置 和 (),如果 ,则区间 的净电力非负
代码解析
前缀和计算与离散化
cin >> n; for (int i = 1; i <= n; i++) cin >> a[i], s[i] = s[i - 1] + a[i]; vector<ll> X; for (int i = 0; i <= n; i++) X.push_back(s[i]); // 检查总电力是否足够 if (s[n] < 0) { cout << "-1\n"; return 0; } // 离散化前缀和以便树状数组处理 sort(X.begin(), X.end()); for (int i = 0; i <= n; i++) s[i] = lower_bound(X.begin(), X.end(), s[i]) - X.begin() + 1;
动态规划与树状数组优化
struct BIT { int c[N]; void add(int x, int v) { while (x <= n + 1) { c[x] = min(c[x], v); // 维护最小值 x += x & -x; } } int qry(int x) { int ret = 1e9; while (x) { ret = min(ret, c[x]); x -= x & -x; } return ret; } } bit; // 初始化 fill(bit.c + 1, bit.c + n + 2, 1e9); bit.add(s[0], f[0] - 0); // 初始状态 // 动态规划转移 for (int i = 1; i <= n; i++) { f[i] = bit.qry(s[i]) + i - 1; bit.add(s[i], f[i] - i); }
算法正确性
状态定义
表示处理到第 个城市时的最小成本。
状态转移
对于位置 ,寻找最近的 使得 ,然后:
这表示从 到 需要连接线路,成本为距离 。
树状数组优化
树状数组维护对于每个前缀和值 的最小 ,这样可以在 时间内找到最优的 。
复杂度分析
- 时间复杂度:
- 离散化:
- 动态规划:
- 空间复杂度:
- 1
信息
- ID
- 3448
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者