CF1918D Blocking Elements 题解
KingPowers · · 题解
感觉比 C 题还简单啊。
答案显然具有单调性,因此考虑二分转化为判定性问题。
假设我们要求代价不超过
考虑 dp,在保证每一段的和不超过
其中
不难发现直接转移是
注意的一点是,只需要存在一个
时间复杂度
赛时偷懒写的小根堆,复杂度会多一个
#include<bits/stdc++.h>
#define int long long
#define For(i, a, b) for(int i = (a); i <= (b); i++)
#define Rof(i, a, b) for(int i = (a); i >= (b); i--)
using namespace std;
const int N = 5e5 + 5;
int n, a[N], f[N], sum[N];
bool check(int mid){
For(i, 1, n) f[i] = 1e18;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>>q;
q.push({0, 0}); f[0] = 0; int pos = 0;
For(i, 1, n){
while(pos + 1 < i && sum[i - 1] - sum[pos] > mid) pos++;
while(q.top().second < pos) q.pop();
f[i] = q.top().first + a[i];
q.push({f[i], i});
}
For(i, 1, n) if(f[i] <= mid && sum[n] - sum[i] <= mid) return true;
return false;
}
void Solve(){
cin >> n;
For(i, 1, n) cin >> a[i];
For(i, 1, n) sum[i] = sum[i - 1] + a[i];
int l = 0, r = 1e16, ans = -1;
while(l <= r){
int mid = (l + r) >> 1;
if(check(mid)) r = mid - 1, ans = mid;
else l = mid + 1;
}
cout << ans << '\n';
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int T = 1; cin >> T;
while(T--) Solve();
return 0;
}