题解:P9097 [PA2020] Elektrownie i fabryki
lovely_nst · · 题解
P9097 [PA2020] EIF
前置
-
分段 DP
-
树状数组
-
二分等其它算法
正文
设
时间复杂度为
接下来要优化,发现转移方程可以写成:
只与
AC Code
#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;
}