[ARC189D] Takahashi is Slime 题解
传送门
不难想到一个暴力,对于每一个 \(K\),都一个个向左右扩展,直到不能扩展为止。这个做法是 \(O(n^2)\) 的,我们考虑优化。
我们将一个个扩展改成一次性扩展许多个格子。即循环进行下面操作:
- 向左扩展到不能扩展。
- 向右扩展到不能扩展。
我们使用二分,看看每次扩展最远到哪。
时间复杂度 \(O(n \log n \log V)\),带点(小)常数,5s 随便过。
为什么这样是对数平方级别的呢?我们考虑每次最多扩展多少次。发现每扩展 \(3\) 次,自身大小就会增加一倍。最劣的情况就是 \(V,\frac{V}{2},\frac{V}{4},\frac{V}{8},...\) 排列,这样每次只能扩展一格。那最多也只会进行 \(\log V\) 次扩展。算上二分,就是对数平方级别的复杂度。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define Linf 0x3f3f3f3f3f3f3f3f
#define int long long
#define pii pair<int, int>
#define all(v) v.begin(), v.end()
using namespace std;
//#define filename "xxx"
#define FileOperations() freopen(filename".in", "r", stdin), freopen(filename".out", "w", stdout)
namespace Traveller {
const int N = 5e5+2;
int n, a[N], sum[N];
int search1(int sz, int n) {
int L = 1, R = n;
while(L < R) {
int mid = L + R >> 1;
if(sz > sum[n-1] - sum[mid-1]) R = mid;
else L = mid+1;
}
return L;
}
int search2(int sz, int l) {
int L = l, R = n;
while(L < R) {
int mid = L + R + 1 >> 1;
if(sz > sum[mid] - sum[l]) L = mid;
else R = mid-1;
}
return L;
}
void main() {
cin >> n;
for(int i = 1; i <= n; ++i) {
scanf("%lld", &a[i]);
sum[i] = sum[i-1] + a[i];
}
for(int i = 1; i <= n; ++i) {
int ans = a[i], l = i, r = i;
while(true) {
int p1 = search1(ans, l);
int p2 = search2(ans, r);
if(p1 == l && p2 == r) break;
ans += sum[l-1] - sum[p1-1], l = p1;
ans += sum[p2] - sum[r], r = p2;
}
printf("%lld ", ans);
}
puts("");
}
}
signed main() {
#ifdef filename
FileOperations();
#endif
Traveller::main();
return 0;
}

浙公网安备 33010602011771号