3.9 美团笔试
24年第一次笔试...
T1, 模拟
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k; cin >> n >> k;
string s; cin >> s;
int current = 0;
for (auto c : s) {
if (c == 'M' || c == 'T') current++;
}
int res = min(int(s.length()), current+k);
cout << res << endl;
return 0;
}
T2,模拟
注意数据范围,使用long
#include<bits/stdc++.h>
using namespace std;
int main() {
int n, q; cin >> n >> q;
long tmp, zeroCnt = 0, nonZeroSum = 0;
for (int i = 0; i < n; i++) {
cin >> tmp;
if (tmp == 0) {
zeroCnt++;
} else {
nonZeroSum += tmp;
}
}
while (q--) {
long l, r;
cin >> l >> r;
cout << nonZeroSum + zeroCnt*l << ' ' << nonZeroSum+zeroCnt*r << endl;
}
return 0;
}
T3,二维前缀和
#include<bits/stdc++.h>
using namespace std;
int main() {
int n; cin >> n;
vector<string> mat(n);
for (int i = 0; i < n; i++) cin >> mat[i];
int pre[205][205]{};
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
pre[i+1][j+1] = pre[i+1][j] + pre[i][j+1] - pre[i][j] + (mat[i][j]=='1');
}
}
for (int len = 1; len <= n; len++) {
if (len % 2 == 1) {
cout << 0 << endl;
continue;
}
int current = 0, target = len*len/2;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
int endI = i+len-1, endJ =j+len-1;
if (endI > n-1 || endJ > n-1) continue;
int val = pre[endI+1][endJ+1] - pre[endI+1][j] - pre[i][endJ+1] + pre[i][j];
if (val == target) current++;
}
}
cout << current << endl;
}
return 0;
}
T4,前缀和 + 滑动窗口
(注意数据范围, 使用long)
思路:
- 给出的数字都是不为0的,最终乘积的0 一定是由素因子 2, 5构成的, 因此主要关心区间内2、5的数量
- 要求删除区间后0的数量应该大于等于k,即删除区间后剩下的数中 素因子2、5的数量必须同时大于等于k
滑动窗口: 枚举以i开始的可以删除的子串数量,for循环内部while结束后, i-j对应的子串是不符合条件的,但i到 [i+1、i+2、 ... j-1]都是满足条件的。
复杂度 O(n)
#include<bits/stdc++.h>
using namespace std;
const int MaxN = 1e5+5;
int main() {
int n, k; cin >> n >> k;
int arr[n];
long pre2[MaxN]{}, pre5[MaxN]{};
for (int i = 0; i < n; i++) {
cin >> arr[i];
int cntFactor2 = 0, cntFactor5 = 0;
for (int x = arr[i]; x % 2 == 0; x /= 2) cntFactor2++;
for (int x = arr[i]; x % 5 == 0; x /= 5) cntFactor5++;
pre2[i+1] += pre2[i] + cntFactor2;
pre5[i+1] += pre5[i] + cntFactor5;
}
long res = 0, zeroCnt = min(pre2[n], pre5[n]);
for (int i = 0, j = 0; i < n; i++) {
while (j < n) {
int range2 = pre2[j+1] - pre2[i];
int range5 = pre5[j+1] - pre5[i];
int remain2 = pre2[n] - range2;
int remain5 = pre5[n] - range5;
if (min(remain2, remain5) < k) break;
j++;
}
res += max(j-i, 0);
}
cout << res << endl;
return 0;
}
T5, 并查集、离散化、逆向思维
笔试时想到了并查集,但没写出来,写了个dfs,超时~
笔试后参考@Y丶bs大佬的思路使用并查集实现了下。 ref: https://www.nowcoder.com/discuss/596124837462978560
并查集写法
#include <bits/stdc++.h>
using namespace std;
const int MaxN = 4e5+5;
int fa[MaxN];
int find(int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
void merge(int x, int y) {
int faX = find(x);
int faY = find(y);
if (faX != faY) {
fa[faX] = faY;
}
}
int main() {
iota(fa, fa+MaxN, 0); // 初始化fa数组
unordered_set<int> points; // 记录所有点, 离散化使用
int n, m, q; cin >> n >> m >> q;
vector<vector<int>> edges;
for (int i = 0; i < m; i++) {
int a, b; cin >> a >> b;
points.insert(a);
points.insert(b);
edges.push_back({a, b});
}
unordered_map<int, unordered_set<int>> delEdgeMap;
vector<vector<int>> ops;
while (q--) {
int op, u, v; cin >> op >> u >> v;
points.insert(u);
points.insert(v);
ops.push_back({op, u, v});
if (op == 1) {
delEdgeMap[u].insert(v);
delEdgeMap[v].insert(u);
}
}
int idx = 0; // 离散化初始idx
unordered_map<int, int> val2Idx;
for (auto u : points) val2Idx[u] = idx++;
// 建立并查集、不使用删除的边
for (auto &e : edges) {
int u = e[0], v = e[1];
if (delEdgeMap.count(u) && delEdgeMap[u].count(v)) {
continue;
}
merge(val2Idx[u], val2Idx[v]);
}
vector<bool> result;
reverse(ops.begin(), ops.end()); // 反向遍历
for (auto &item : ops) {
int op = item[0], u = item[1], v = item[2];
int idxU = val2Idx[u], idxV = val2Idx[v];
if (op == 1) { // 加边操作
merge(idxU, idxV);
continue;
}
if (find(idxU) == find(idxV)) {
result.push_back(true);
} else {
result.push_back(false);
}
}
for (int i = result.size()-1; i >= 0; i--) {
if (result[i]) {
printf("Yes\n");
} else {
printf("No\n");
}
}
return 0;
}
暴力dfs解法(超时...)
#include <bits/stdc++.h>
using namespace std;
int n, m, q;
unordered_map<int, unordered_map<int, bool>> g;
bool dfs(int u, int parent, int target) {
if (u == target) {
return true;
}
for (auto &[v, ok] : g[u]) {
if (v != parent && ok && dfs(v, u, target)){
return true;
}
}
return false;
}
int main() {
cin >> n >> m >> q;
for (int i = 0; i < m; i++) {
int a, b; cin >> a >> b;
g[a][b] = true;
g[b][a] = true;
}
while (q--) {
int op, u, v;
cin >> op >> u >> v;
if (op == 1) {
g[u][v] = false;
g[v][u] = false;
continue;
}
if (dfs(u, -1, v)) {
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
}
return 0;
}
#美团2025实习生笔试##实习#
