6845. 【2020.11.02提高组模拟】梯度弥散

(something extra)

(mmp),考试的时候还看错题了。。。以为是导入一次(x),只能发射一次,求(sum x)
然而:
感觉自己看题的时候都不怎么仔细了。。。这种错误下次还是不要犯了吧。。。

(Solution)

考虑按(c)分情况讨论。
对于(c=0),可以直接扫一遍,注意要判(-1)
对于(c=1),二分答案判断即可,判断用差分即可。
对于(c=2),二分答案判断即可,判断用差分即可,差分将式子拆开即可。
细节繁多,(WA)了好几遍。。。

(Code)

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
#define ll long long
#define ls (x << 1)
#define rs (x << 1 | 1)
#define mem(x, a) memset(x, a, sizeof x)
#define mpy(x, y) memcpy(x, y, sizeof y)
#define fo(x, a, b) for (int x = (a); x <= (b); x++)
#define fd(x, a, b) for (int x = (a); x >= (b); x--)
#define go(x) for (int p = tail[x], v; p; p = e[p].fr)
using namespace std;
int Num, n, c, K, a[N], ti_ = 0;
ll tag[N], dd[N], ee[N];

inline int read() {
	int x = 0, f = 0; char c = getchar();
	while (c < '0' || c > '9') f = (c == '-') ? 1 : f, c = getchar();
	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return f ? -x : x;
}

bool check(int mid) {
	mem(tag, 0), mem(dd, 0); mem(ee, 0);
	ll s = 0, hs = 0, sum = 0; ti_ = 0;
	fo(i, 1, n) {
		s -= dd[i], sum -= tag[i], hs -= ee[i];
		ll nd = a[i] - s + 2LL * i * sum - 1LL * i * i * hs;
		if (nd <= 0) continue;
		int cs = nd / (mid * mid) + (nd % (mid * mid) != 0); ti_ += cs;
		s += 1LL * (mid + i) * (mid + i) * cs, sum += 1LL * (mid + i) * cs, hs += cs;
		ee[min(n + 1, i + mid)] += cs;
		tag[min(n + 1, i + mid)] += 1LL * (mid + i) * cs;
		dd[min(n + 1, i + mid)] += 1LL * (mid + i) * (mid + i) * cs;
	}
	return ti_ <= K;
}

bool judge(int mid) {
	mem(tag, 0);
	int s = 0, hs = 0; ti_ = 0;
	fo(i, 1, n) {
		s -= hs, hs -= tag[i];
		int nd = a[i] - s;
		if (nd <= 0) continue;
		int cs = nd / mid + (nd % mid != 0);
		s += cs * mid, ti_ += cs, hs += cs;
		tag[min(n + 1, i + mid)] += cs;
	}
	return ti_ <= K;
}

int main()
{
	freopen("dispersion.in", "r", stdin);
	freopen("dispersion.out", "w", stdout);
	Num = read(), n = read(), c = read(), K = read();
	fo(i, 1, n) a[i] = read();
	if (c == 0) {
		int s = 0;
		fo(i, 1, n) {
			s -= tag[i];
			int nd = a[i] - s;
			if (nd <= 0) continue;
			s += nd, ti_ += nd;
			tag[min(n + 1, i + nd)] += nd;
		}
		if (ti_ > K) printf("-1
");
		else printf("0
");
		return 0;
	}
	else if (c == 1) {
		int l = 1, r = 1e7, mid;
		while (l <= r) {
			mid = (l + r) >> 1;
			if (judge(mid)) r = mid - 1;
			else l = mid + 1;
		}
		printf("%d
", r + 1);
	}
	else {
		check(10);
		int l = 0, r = 1e7, mid;
		while (l <= r) {
			mid = (l + r) >> 1;
			if (check(mid)) r = mid - 1;
			else l = mid + 1;
		}
		printf("%d
", r + 1);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/jz929/p/13916779.html