【二分】luogu_P7405 [JOI 2021 Final] 雪玉

题意

在一条无限长的数轴上,有\(N\)个雪球,编号为\(1 \sim N\),第\(i\)个雪球在第\(A_i\)个点上。

刚开始,整条数轴覆盖满了雪,接下来\(Q\)天将会刮起大风,第\(j\)天的风力强度为\(W_j\),如果\(W_j\)为正数,所有雪球都朝右移动\(W_j\)个单位长度,如果\(W_j\)为负数,所有雪球都朝左移动\(-W_j\)个单位长度。
当一个区间\([a,a+1]\)被雪覆盖时,雪球滚上去雪球的质量会加一,这一个区间里的雪也会被清空。

刚开始每一个雪球的质量均为\(0\),而这\(Q\)天里也没有再下雪。
问这\(Q\)天结束后每个雪球的质量。

思路

可以发现对于相邻两个雪球之间的区间里的雪一定是贡献给了这两个球。

那么对于每个区间,要找出左右雪球占的质量。

发现向左向右的最大值是具有单调性的,可以进行二分。

代码

#include <cstdio>
#define int long long

int n, q;
int p[200001], l[200001], r[200001], ans[200001];

void calc(int cur, int len) {
	if (l[q] + r[q] <= len) {
		ans[cur] += r[q];
		ans[cur + 1] += l[q];
		return;
	}
	int L = 1, R = q, mid;
	while (L < R) {
		int mid = L + R >> 1;
		if (l[mid] + r[mid] <= len)
			L = mid + 1;
		else
			R = mid;
	}
	if (l[L] == l[L - 1])
		ans[cur] += len - l[L], ans[cur + 1] += l[L];
	else
		ans[cur] += r[L], ans[cur + 1] += len - r[L];
}

signed main() {
	scanf("%lld %lld", &n, &q);
	for (int i = 1; i <= n; ++i)
		scanf("%lld", &p[i]);
	for (int i = 1, x, cur = 0; i <= q; ++i) {
		scanf("%lld", &x);
		cur += x;
		l[i] = l[i - 1] > -cur ? l[i - 1] : -cur;
		r[i] = r[i - 1] > cur ? r[i - 1] : cur;
	}
	ans[1] += l[q];
	ans[n] += r[q];
	for (int i = 1; i < n; ++i)
		calc(i, p[i + 1] - p[i]);
	for (int i = 1; i <= n; ++i)
		printf("%lld\n", ans[i]);
}
posted @ 2021-07-18 21:39  nymph181  阅读(63)  评论(0)    收藏  举报