牛客小白月赛30(个人题解)
最近沉迷写前端代码,现在缓过来简单补下
比赛链接:https://ac.nowcoder.com/acm/contest/9667#question
A:黑白边
简单的并查集模板
B:最好的宝石
待补
C:滑板上楼梯
math
// Author : RioTian
// Time : 20/12/07
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int main() {
// freopen("in.txt", "r", stdin);
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
ll n, cnt = 0;
cin >> n;
ll ans = n / 4;
cnt += ans * 2;
ans = n % 4;
if (ans < 3)
cnt += ans;
else
cnt++;
cout << cnt << endl;
}
D:GCD
素数筛反向选
// Author : RioTian
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int n;
bool isPrime[N];
int main() {
// freopen("in.txt", "r", stdin);
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n;
int cnt = 0;
for (int i = 2; i <= n; i++) {
if (!isPrime[i]) {
cnt++;
for (int j = i * 2; j <= n; j += i) {
isPrime[j] = 1;
}
}
}
// cout << cnt << endl;
cout << (n <= 3 ? -1 : cnt + 2) << endl;
}
E:牛牛的加法
模拟题
如果两数字位数不同就先补零便于后面处理
// Author : RioTian
// Time : 20/12/07
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
string a, b, ans;
int cot = 0, len;
bool lin;
int main() {
// freopen("in.txt", "r", stdin);
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> a >> b;
if (a.size() > b.size()) {
cot = a.size() - b.size();
while (cot--)
b = '0' + b;
} else {
cot = b.size() - a.size();
while (cot--)
a = '0' + a;
}
len = a.size();
ans = "";
lin = true;
for (int i = 0; i < len; i++) {
if ((a[i] - '0' + b[i] - '0') % 10 == 0 && lin)
continue;
lin = false;
ans += (char)((a[i] - '0' + b[i] - '0') % 10 + '0');
}
if (ans.size() == 0)
ans += "0";
cout << ans << endl;
}
F:石子合并
模拟一下样例1,会发现16 + 15,容易发下16为5项和,而\(15 = max(a[i]) * (n - 2)\)
// Author : RioTian
// Time : 20/12/07
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int n;
ll a[N];
int main() {
// freopen("in.txt", "r", stdin);
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> a[i];
ll cnt = 0, Max = 0;
for (int i = 1; i <= n; ++i) {
Max = max(Max, a[i]);
cnt += a[i];
}
cout << Max * (n - 2) + cnt;
}
G:滑板比赛
类似二分图,在满足条件的情况下尽量增加匹配数。
直接写二分图肯定很麻烦,但转过来一想,为数组排序呢?
\[2\ 3\ 4\ 6\ 7\\
2\ 3\ 4\ 4\ 6\\
\\
从后往前匹配对象(数值尽量相近,这样就可以把小的数字留给其他的)\\
7匹配6\\
6匹配4\\
4匹配3\\
3匹配2\\
由于不存在空闲比2小的数字了,所以最终成功匹配数为4
\]
// Author : RioTian
// Time : 20/12/07
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int n, m;
ll a[N], b[N];
int main() {
// freopen("in.txt", "r", stdin);
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; ++i)
cin >> a[i];
for (int i = 1; i <= m; ++i)
cin >> b[i];
sort(a + 1, a + 1 + n);
sort(b + 1, b + 1 + m);
int i, j;
int ans = 0, l = 1, r = n;
for (i = m; i >= 1; i--) {
if (b[i] < a[r])
r--, ans++;
else
l++;
}
cout << ans << endl;
}
H:第 k 小
看到题的瞬间想用线段树,但简单算了下时间复杂度,可能会超时,所以转而想了想主席树(没了解的同学可以看这里:Here),但觉得牛客应该不会在小白赛出这种码量大的题。
被迫无奈看了下题解,发现原来快速写下优先队列即可(都没想到这个)
以下是AC代码
// Author : RioTian
// Time : 20/12/07
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
ll a[N];
priority_queue<ll> que;
int main() {
// freopen("in.txt", "r", stdin);
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n, m, k;
cin >> n >> m >> k;
for (int i = 1; i <= n; ++i)
cin >> a[i];
sort(a + 1, a + 1 + n);
int ans = min(n, k);
for (int i = 1; i <= ans; ++i)
que.push(a[i]);
int opt, x;
while (m--) {
cin >> opt;
if (opt == 1) {
cin >> x;
if (que.size() <= k - 1)
que.push(x);
else {
if (x > que.top())
continue;
que.push(x), que.pop();
}
} else {
if (que.size() != k)
cout << -1 << endl;
else
cout << que.top() << endl;
}
}
}
I:区间异或
J:小游戏
这两个待补