专栏文章
题解:P9097 [PA2020] Elektrownie i fabryki
P9097题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miqh4n5t
- 此快照首次捕获于
- 2025/12/04 04:43 3 个月前
- 此快照最后确认于
- 2025/12/04 04:43 3 个月前
P9097 [PA2020] EIF
前置
-
分段 DP
-
树状数组
-
二分等其它算法
正文
设 为以 为一段区间结束点,前 个点的最小连边数。可以易得以下转移方程:
时间复杂度为 ,用前缀和可优化为 。
接下来要优化,发现转移方程可以写成:
只与 的值有关。若前缀和 ,则 。因此用树状数组维护即可,记得离散化。
AC Code
CPP#include <bits/stdc++.h>
#define int long long
using namespace std;
int n , m , x , s[500005] , S[500005] , d[500005] , f[500005];
void upd (int pos , int c) { while (pos <= m) d[pos] = min (d[pos] , c) , pos += (pos & -pos); }
int qry (int pos) { int ans = 1e9; while (pos) ans = min (ans , d[pos]) , pos -= (pos & -pos); return ans; }
signed main ()
{
ios::sync_with_stdio (0) , cin.tie () , cout.tie ();
cin >> n;
for (int i = 1;i <= n;i ++)
cin >> x , S[i] = s[i] = s[i - 1] + x , d[i] = 1e18;
d[n + 1] = 1e18;
sort (S + 1 , S + n + 2);
m = unique (S + 1 , S + n + 2) - S - 1;
for (int i = 1;i <= m;i ++)
if (S[i] == 0)
upd (i , 0);
for (int i = 1;i <= n;i ++)
{
int fd = lower_bound (S + 1 , S + m + 1 , s[i]) - S;
f[i] = qry (fd) + i - 1;
upd (fd , f[i] - i);
}
if (f[n] > n)
f[n] = -1;
cout << f[n];
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...