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