美团2025年春招第一场笔试【技术方向】个人题解
题目:10 道单选 + 3 道算法题
结果:只做出前两道题,第三题暴力0分
题图在网上找的
第一题:字符串解密
按规则模拟即可,为了防止可能出现的问题我取了下模,按理来说 p 每次乘法都可能溢出的,但是貌似没有设置这种坑
#include <bits/stdc++.h>
using namespace std;
int main() {
int T;
cin >> T;
while(T--){
string s;
cin >> s;
string t;
int p = 0;
for(auto c : s){
if(isalpha(c)){
int len = t.size();
if(len){
p %= len;
t = t.substr(p, len - p) + t.substr(0, p);
}
if(c == 'R') reverse(t.begin(), t.end());
else t += c;
p = 0;
}else{
p = p * 10 + c - '0';
}
}
cout << t << endl;
}
return 0;
}
第二题:小美架炮
我的做法是排序一下,把相同横坐标或者纵坐标的点一块计算。
以相同横坐标为例,假设有5个点 a, b, c, d, e 横坐标相同,纵坐标递增,则 a,b,d,e 都能打到 1 个炮,c 能打到 2 个炮
纵坐标同理这样统计答案即可
复杂度还是排序的 O(nlogn) 吧
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 4;
struct node{
int x, y, id;
};
int ans[N];
vector<node>a;
int main() {
int n;
cin >> n;
for(int x, y, i = 1;i <= n;i++){
cin >> x >> y;
a.push_back({x, y, i}); // 记录答案 id
}
// 按横坐标排序,相同横坐标一块计算往纵坐标方向打的数量
sort(a.begin(), a.end(), [](const node& u, const node& v)->bool{
return u.x == v.x ? u.y < v.y : u.x < v.x;
});
for(int i = 0;i < n;i++){
int j = i;
while(j < n && a[i].x == a[j].x) j++;
j--;
// [i, j] 区间内横坐标相等
for(int k = i;k <= j;k++){
if(k - 2 >= i) ans[a[k].id]++; // 往下打
if(k + 2 <= j) ans[a[k].id]++; // 往上打
}
i = j;
}
// 同理的,按纵坐标排序
sort(a.begin(), a.end(), [](const node& u, const node& v)->bool{
return u.y == v.y ? u.x < v.x : u.y < v.y;
});
for(int i = 0;i < n;i++){
int j = i;
while(j < n && a[i].y == a[j].y) j++;
j--;
for(int k = i;k <= j;k++){
if(k - 2 >= i) ans[a[k].id]++;
if(k + 2 <= j) ans[a[k].id]++;
}
i = j;
}
for(int i = 1;i <= n;i++)
cout << ans[i] << endl;
return 0;
}
第三题:有根树
当场感觉是 LCA 最近公共祖先,但是忘记了板子,就想着暴力能得多少是多少吧,结果通过 0%
看了其他大佬的简略题解,自己写了下代码,可以通过样例,不知道能过吗。。。如果题目开放了测一下看看
前置知识:倍增,最近公共祖先
时间复杂度 O(nlogn)
假设 u,v 的最近公共祖先是 x,u 到 x 的 B U G 覆盖状态分别映射为 1 2 4(代码中的 bug 数组)
v 到 x 的 B U G 覆盖状态分别映射为 4 2 1 (代码中的 gub 数组)
比较难处理的是 B U G 的顺序问题,这里我也不确定对不对,有大佬的话可以指正,只做过 LCA 板子题,倍增的时候带状态的也是第一次做。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5 + 6;
vector<int> a[N];
int n, m, d[N], fa[N][20], lg2[N], bug[N][20], gub[N][20];
char s[N];
int ok;
// y 比 x 离根近
int update(int x, int y){
int ans = x;
if((y & 1))
ans |= 1;
// 左边是先有 B 才填 U,右边是先有 G 才填 U
if((y & 2) && (ans & 1))
ans |= 2;
if((y & 4) && (ans & 2))
ans |= 4;
return ans;
}
void dfs(int now, int f) {
d[now] = d[f] + 1;
fa[now][0] = f;
bug[now][0] |= (s[now] == 'B'); // B -> 1
bug[now][0] |= ((s[now] == 'U') << 1); // U -> 2
bug[now][0] |= ((s[now] == 'G') << 2); // G -> 4
gub[now][0] |= (s[now] == 'G');
gub[now][0] |= ((s[now] == 'U') << 1);
gub[now][0] |= ((s[now] == 'B') << 2);
int range = lg2[d[now]];
for(int i = 1;i <= range;i++) {
fa[now][i] = fa[fa[now][i - 1]][i - 1];
bug[now][i] = update(bug[now][i - 1], bug[fa[now][i - 1]][i - 1]);
gub[now][i] = update(gub[now][i - 1], gub[fa[now][i - 1]][i - 1]);
}
for(auto nxt : a[now])
dfs(nxt, now);
}
int LCA(int x, int y) {
int lok = 0, rok = 0;
while (d[x] > d[y]) {
lok = update(lok, bug[x][lg2[d[x] - d[y]]]);
x = fa[x][lg2[d[x] - d[y]]];
}
while (d[y] > d[x]) {
rok = update(rok, gub[y][lg2[d[y] - d[x]]]);
y = fa[y][lg2[d[y] - d[x]]];
}
lok = update(lok, bug[x][0]);
rok = update(rok, gub[y][0]);
if (x == y){
// 左边 BUG 或者 右边 GUB,或者 左边 B 和 右边 UG ...
if(lok == 7 || rok == 7 || (lok == 1 && rok == 3) || (lok == 3 && rok == 1) || (lok == 3 && rok == 3))
return 1;
else return 0;
}
for (int i = lg2[d[x]]; i >= 0; i--) {
if (fa[x][i] != fa[y][i]){
lok = update(lok, bug[x][i]);
rok = update(rok, gub[x][i]);
x = fa[x][i], y = fa[y][i];
}
}
lok = update(lok, bug[x][0]);
rok = update(rok, gub[x][0]);
lok = update(lok, bug[fa[x][0]][0]);
if(lok == 7 || rok == 7 || (lok == 1 && rok == 3) || (lok == 3 && rok == 1) || (lok == 3 && rok == 3))
return 1;
else return 0;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 2; i <= n; i++)
lg2[i] = lg2[i - 1] + ((1 << (lg2[i - 1] + 1)) == i);
for (int i = 1, fa; i <= n; i++) {
scanf("%d", &fa);
a[fa].push_back(i);
}
scanf("%s", s + 1);
dfs(1, 0);
while (m--) {
int x, y;
scanf("%d%d", &x, &y);
ok = LCA(x, y);
if(ok) cout << "NO" << endl;
else cout << "YES" << endl;
}
return 0;
}
/*
5 3
0 1 1 2 2
AUGBC
4 3
4 5
4 1
9 3
0 1 1 2 2 3 3 4 8
CDBUGGCGB
7 8
8 6
9 6
*/
查看11道真题和解析