归档 221024 - 221030 | 做题记录

E. Best Cow Fences -221025

https://www.acwing.com/problem/content/104/

有意思的题目。

因为丢在了二分的链接里,我们思考一下究竟是什么具有单调性。

硬要说的话,平均值的大小是有单调性的。对于平均值最大的区间,若其平均值大于 \(x\),明显也会大于 \(x-1\)

这种形式的「单调性」限制了我们的 check 只能朝一个方向写:给出一个平均值 \(x\),判断是否存在长度 \(\ge L\) 的区间,其平均值大于 \(x\)

即:

\[\frac{\sum_{i=l}^r A_i}{r-l+1} \ge x \]

转化为:

\[\begin{aligned} \sum_{i=l}^r A_i &\ge x\times(r-l+1) \newline A_l+A_{l+1}+\cdots+A_r &\ge x + x + \cdots + x \newline (A_l-x)+(A_{l+1}-x)+\cdots+(A_r-x) &\ge 0 \newline \sum_{i=l}^r A_i-x &\ge 0 \end{aligned} \]

所以对于一次 check,我们把所有 \(A\) 中的元素减去 \(x\),用滑窗找到最大子段和,判断是否大于等于 \(0\) 即可。

注意这里我们把原本寻找单调性的条件「平均值最大的区间的平均值是否大于 \(x\)」转化为了「是否存在区间的平均值大于 \(x\)」。不难发现,当前者满足时,后者也满足;后者满足时,前者也满足,所以两者等价,这种转化是正确的(中肯的,一针见血的)。

namespace XSC062 {
using ll = long long;
const ll inf = 1e12;
const int maxn = 1e5 + 5;
int n, k;
int q[maxn];
ll l, mid, r, res;
ll a[maxn], p[maxn];
inline ll max(ll x, ll y) {
	return x > y ? x : y;
}
inline int check(ll x) {
	int h = 1, t = 0;
	for (int i = 1; i <= n; ++i) {
		p[i] = a[i] - x + p[i - 1];
		if (h <= t) {
			if (p[i] - p[q[h]] >= 0)
				return 1;
		}
		if (i - k + 1 >= 0) {
			while (h <= t && p[i - k + 1] < p[q[t]])
				--t;
			q[++t] = i - k + 1;
		}
	}
	return 0;
}
int main() {
	scanf("%d %d", &n, &k);
	for (int i = 1; i <= n; ++i)
		scanf("%lld", &a[i]), a[i] *= 1000;
	l = -inf, r = inf;
	while (l <= r) {
		mid = (l + r) >> 1;
		if (check(mid)) {
			res = mid;
			l = mid + 1;
		}
		else r = mid - 1;
	}
	printf("%lld", res);
	return 0;
}
} // namespace XSC062

F. Lost Cows - 221025

倒序处理序列。

容易发现,\(A_i\) 表示的是删掉 \(i+1\sim n\) 后的 rank,所以我们随便打个线段树什么的就好了。

namespace XSC062 {
#define lt (p << 1)
#define rt (lt | 1)
using namespace fastIO;
const int maxn = 1e5 + 5;
struct _ { int l, r, u; };
int n;
int a[maxn];
_ t[maxn << 2];
inline void pushup(int p) {
	t[p].u = t[lt].u + t[rt].u;
	return;
}
void bld(int p, int l, int r) {
	t[p].l = l;
	t[p].r = r;
	if (l == r) {
		t[p].u = 1;
		return;
	}
	int mid = (l + r) >> 1;
	bld(lt, l, mid);
	bld(rt, mid + 1, r);
	pushup(p);
	return;
}
void add(int p, int x, int v) {
	if (t[p].l == t[p].r) {
		t[p].u += v;
		return;
	}
	int mid = (t[p].l + t[p].r) >> 1;
	if (x <= mid)
		add(lt, x, v);
	else add(rt, x, v);
	pushup(p);
	return;
}
int getrank(int p, int k) {
	if (t[p].l == t[p].r)
		return t[p].l;
	if (t[lt].u >= k)
		return getrank(lt, k);
	return getrank(rt, k - t[lt].u);
}
int main() {
	read(n);
	for (int i = 2; i <= n; ++i)
		read(a[i]);
	bld(1, 1, n);
	for (int i = n; i > 1; --i) {
		a[i] = getrank(1, a[i] + 1);
		add(1, a[i], -1);
	}
	a[1] = getrank(1, 1);
	for (int i = 1; i <= n; ++i)
		print(a[i], '\n');
	return 0;
}
} // namespace XSC062

H. Tree - 221025

首先我们根据题目中的明示猜测需要用到最小生成树。

题意可以转化为:找到一个恰好有 \(\text{need}\) 条白边的最小生成树。

所以要处理的问题就是:怎么让最小生成树包含恰好 \(\text{need}\) 条白边。

首先找单调性。


C. 车站分级

一些鲜花

Yeah↗, I liked↘ it!

posted @ 2022-10-25 13:20  XSC062  阅读(48)  评论(0编辑  收藏  举报