2022.7.31 LeetCode AcWing周赛

LeetCode

BFS 层序遍历模板题

https://leetcode.cn/problems/maximum-level-sum-of-a-binary-tree/solution/1161-by-sen-xm-3q4t/

AcWing 周赛第二题

单点修改 + 区间修改 + 区间查询

如果暴力地记录每一种的出现次数,修改是O(1)的,但是每次查询都是O(n)的。查询是瓶颈,考虑一种数据结构,可以更快地查询一组数的出现次数。
f[i]记录出现次数大于等于i的种类数,可以看到,这里不是以种类作索引,而是以出现次数作为下标,这样就可以O(1)的实现查询。构造新数据结构的时候可以考虑,索引和值的含义对换从而构造新的数据结构。
而对f[i]的维护,也可以记录当前每种的出现次数,由于本题中出现次数恒增,因而可以O(1)的维护f数组,从而使总的时间复杂度降为线性的O(1)。

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;

int delta = 1;
int n, m, t, a[N], f[N];

int main() {
	scanf("%d %d", &n, &m);
	while (m--) {
		scanf("%d", &t);
		f[++a[t]]++;
		if (f[delta] == n) {
			putchar('1');
			delta++;
		} else
			putchar('0');
	}

	return 0;
}

AcWing 周赛第三题

思路比较简单。

子集最大值一定是原集合最大值。否则,将选取的子集最大值更换为原集合最大值后,结果一定更优。同理可证,较小的一部分一定是从原集合最小值开始的一段连续数列。
那么问题就在于如何选取较小集合的长度了。可以看出,对于一组数,我们新加入一个比这组数平均数小的数时,新的这组数平均数会更小。依据这个原理,可以写出判别式如下:

当满足 (sum(a[1~n]) + a[m]+ / (n + 1) > a[n + 1) 时,a[n + 1]可以加入原来较小的那部分数中。又由于最大值每次可以O(1)的取得,而较小的那一部分不会变小,其数量只会递增,所以这个算法的时间复杂度是O(n)的。

结果我脑抽,认为这个动态边界没有解析解,写不出来。结果看题解,一个while不就行了吗????(真的脑抽啊~)可能这是我写代码上面的漏洞吧,认为一些东西实现不出来,但实际上是可以的。

while处理动态边界的情况!!!
while处理动态边界的情况!!!
while处理动态边界的情况!!!

#include <bits/stdc++.h>
using namespace std;

const int N = 5e5 + 10;

int q, x, a[N], n, m;
double tmp;

int main() {
	scanf("%d", &q);
	while (q--) {
		scanf("%d", &x);
		if (x == 1)
			scanf("%d", &a[++m]);
		else {
			while (n + 1 <= m && a[n + 1] < (tmp + a[m]) / (n + 1))
				tmp += a[++n];
			printf("%0.6f\n", a[m] - (a[m] + tmp) / (n + 1));
		}
	}

	return 0;
}
posted @ 2022-07-31 14:59  superPG  阅读(28)  评论(0编辑  收藏  举报