[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;
}

posted @ 2024-12-27 23:17  Water_M  阅读(44)  评论(0)    收藏  举报