美团2024年春招第一场笔试【技术】

小美的平衡矩阵

题目描述

小美拿到了一个 n × n n \times n n×n 的矩阵,其中每个元素是 0 0 0 或者 1 1 1。小美认为一个矩形区域是完美的,当且仅当该区域内 0 0 0 的数量恰好等于 1 1 1 的数量。现在,小美希望你回答有多少个 i × i i \times i i×i 的完美矩形区域。你需要回答 1 ≤ i ≤ n 1 \leq i \leq n 1in 的所有答案。

输入描述

第一行输入一个正整数 n n n,代表矩阵大小。
接下来的 n n n 行,每行输入一个长度为 n n n 01 01 01 串,用来表示矩阵, 1 ≤ n ≤ 200 1\leq n \leq 200 1n200

输出描述

输出 n n n 行,第 i i i 行输出 i × i i \times i i×i 的完美矩形区域的数量。

解题思路

通过二维前缀和可快速得到一个矩形区域内的 0 0 0 1 1 1 的个数。

d p [ i ] [ j ] dp[i][j] dp[i][j] = 以 ( 1 , 1 ) (1,1) (1,1) 为左上角, ( i , j ) (i,j) (i,j) 为右下角的矩形中 1 1 1 的个数,则有如下递推式:

  • d p [ i ] [ j ] = d p [ i − 1 ] [ j ] + d p [ i ] [ j − 1 ] − d p [ i − 1 ] [ j − 1 ] dp[i][j] = dp[i-1][j] + dp[i][j-1] -dp[i-1][j-1] dp[i][j]=dp[i1][j]+dp[i][j1]dp[i1][j1]

对于一个以 ( i , j ) (i,j) (i,j) 为左上角、长为 k k k 的矩形,其中 1 1 1 的个数为:

  • d p [ i + k ] [ j + k ] − d p [ i + k ] [ j − 1 ] − d p [ i − 1 ] [ j + k ] + d p [ i − 1 ] [ j − 1 ] dp[i + k][j + k] - dp[i + k][j - 1] - dp[i - 1][j + k] + dp[i - 1][j - 1] dp[i+k][j+k]dp[i+k][j1]dp[i1][j+k]+dp[i1][j1]
代码实现
const int n = 2e2 + 5;
int dp[n][n];
char s[n];

int main() {
    int n;
    scanf("%d", &n);
    // 输入、计算二维前缀和
    for (int i = 1; i <= n; i++) {
        scanf("%s", s + 1);
        for (int j = 1; j <= n; j++)
            dp[i][j] = dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - 1] + (s[j] == '1');
    }
    // mp[i] = 大小为 i*i 的矩形的数量
    unordered_map<int, int> mp;
    // 枚举每个大小为 i*i 的矩形
    for (int i = 1, t; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            for (int k = 1; i + k <= n && j + k <= n; k += 2) {
                t = dp[i + k][j + k] - dp[i + k][j - 1] - dp[i - 1][j + k] + dp[i - 1][j - 1];
                if (t * 2 == (k + 1) * (k + 1))mp[k + 1]++;
            }
        }
    }
    // 输出每个答案
    for (int i = 1; i <= n; i++)
        printf("%d\n", mp[i]);
    return 0;
}

时间复杂度: O ( n 3 ) O(n^3) O(n3)

空间复杂度: O ( n 2 ) O(n^2) O(n2)

小美的数组询问

题目描述

小美拿到了一个由正整数组成的数组,但其中有一些元素是未知的(用 0 0 0 来表示)。现在小美想知道,如果那些未知的元素在区间 [ l , r ] [l,r] [l,r] 范围内随机取值的话,数组所有元素之和的最小值和最大值分别是多少?共有 q q q 次询问。

输入描述

第一行输入两个正整数 n , q n,q n,q,代表数组大小和询问次数。

第二行输入 n n n 个整数 a i a_i ai ,其中如果输入的 a i a_i ai 0 0 0,那么说明 a i a_i ai 是未知的。

接下来的 q q q 行,每行输入两个正整数 l , r l,r l,r,代表一次询问。

  • 1 ≤ n , q ≤ 1 0 5 1\leq n,q \leq 10^5 1n,q105
  • 0 ≤ a i ≤ 1 0 9 0 \leq a_i \leq 10^9 0ai109
  • 1 ≤ l ≤ r ≤ 1 0 9 1\leq l \leq r \leq 10^9 1lr109
输出描述

输出 q q q 行,每行输出两个正整数,代表所有元素之和的最小值和最大值。

解题思路

l l l 得到最小值,选 r r r 得到最大值。

代码实现
typedef long long ll;

int main() {
    int n, q, cnt = 0;
    ll x, l, r, sum = 0;
    scanf("%d%d", &n, &q);
    while (n--) {
        scanf("%lld", &x);
        x == 0 ? cnt++ : sum += x;
    }
    while (q--) {
        scanf("%lld%lld", &l, &r);
        printf("%lld %lld\n", sum + l * cnt, sum + r * cnt);
    }
    return 0;
}

时间复杂度: O ( n ) O(n) O(n)

空间复杂度: O ( 1 ) O(1) O(1)

小美的 MT

题目描述

M T MT MT 是美团的缩写,因此小美很喜欢这两个字母。现在小美拿到了一个仅由大写字母组成字符串,她可以最多操作 k k k 次,每次可以修改任意一个字符。小美想知道,操作结束后最多共有多少个 M M M T T T 字符?

输入描述

第一行输入两个正整数 n , k n,k n,k,代表字符串长度和操作次数。

第二行输入一个长度为 n n n 的、仅由大写字母组成的字符串。

  • 1 ≤ k ≤ n ≤ 1 0 5 1\leq k \leq n \leq 10^5 1kn105
输出描述

输出操作结束后最多共有多少个 M M M T T T 字符。

解题思路

尽可能修改每个不是 M M M T T T 的字符。

代码实现
int main() {
    int n, k, cnt = 0;
    char c;
    scanf("%d%d\n", &n, &k);
    while (n--) {
        scanf("%c", &c);
        if (c == 'M' || c == 'T')cnt++;
        else if (k > 0)cnt++, k--;
    }
    printf("%d", cnt);
    return 0;
}

时间复杂度: O ( n ) O(n) O(n)

空间复杂度: O ( 1 ) O(1) O(1)

小美的朋友关系

题目描述

小美认为,在人际交往中,但是随着时间的流逝,朋友的关系也是会慢慢变淡的,最终朋友关系就淡忘了。

现在初始有一些朋友关系,存在一些事件会导致两个人淡忘了他们的朋友关系。小美想知道某一时刻中,某两人是否可以通过朋友介绍互相认识?

事件共有 2 2 2 种:

  • 1   u   v 1\ u\ v 1 u v:代表编号 u u u 的人和编号 v v v 的人淡忘了他们的朋友关系。
  • 2   u   v 2\ u\ v 2 u v:代表小美查询编号 u u u 的人和编号 v v v 的人是否能通过朋友介绍互相认识。
输入描述

第一行输入三个正整数 n , m , q n,m,q n,m,q,代表总人数,初始的朋友关系数量,发生的事件数量。

接下来的 m m m 行,每行输入两个正整数 u , v u,v u,v,代表初始编号 u u u 的人和编号 v v v 的人是朋友关系。

接下来的 q q q 行,每行输入三个正整数 o p , u , v op,u,v op,u,v,含义如题目描述所述。

  • 1 ≤ n ≤ 1 0 9 1\leq n \leq 10^9 1n109
  • 1 ≤ m , q ≤ 1 0 5 1\leq m,q \leq 10^5 1m,q105
  • 1 ≤ u , v ≤ n 1\leq u,v \leq n 1u,vn
  • 1 ≤ o p ≤ 2 1\leq op \leq 2 1op2

保证至少存在一次查询操作。

输出描述

对于每次 2 2 2 号操作,输出一行字符串代表查询的答案。如果编号 u u u 的人和编号 v v v 的人能通过朋友介绍互相认识,则输出"Yes"。否则输出"no"。

解题思路
  1. n n n 的规模超过 1 0 6 10^6 106,需要离散化。
  2. 通过并查集可快速判断两人是否为朋友关系。
  3. 并查集不方便删除,故采用反向并查集。对于每个淡忘操作 ( u , v ) (u,v) (u,v),若初始存在 关系 ( u , v ) (u,v) (u,v),则此操作前均存在关系 ( u , v ) (u,v) (u,v),则此操作后均不存在关系 ( u , v ) (u,v) (u,v)。因此,反向顺序进行操作,将删除转为添加,将结果正向输出即为答案。
代码实现
const int n = 1e5 + 5;

// 并查集
int p[n];
// 初始关系、关系记录
set<pair<int, int>> irs, rs;
// 操作
int ops[n][3];
// 离散化
int idx = 0;
unordered_map<int, int> mp;

/**
 * 将编号x转换为离散化后的值
 */
int dsz(int x) {
    if (mp[x] == 0)mp[x] = ++idx;
    return mp[x];
}

/**
 * 找到节点x所在集合的根节点
 */
int find(int x) {
    if (p[x] != x)p[x] = find(p[x]);
    return p[x];
}

/**
 * 合并节点u和节点v所在两个集合
 */
void unite(int u, int v) {
    int pu = find(u), pv = find(v);
    if (pu != pv)p[pu] = pv;
}

int main() {
    int n, m, q, op, u, v;
    scanf("%d%d%d", &n, &m, &q);
    iota(p, p + n, 0);
    // 关系记录 = 初始关系
    while (m--) {
        scanf("%d%d", &u, &v);
        u = dsz(u), v = dsz(v);
        if (u > v)swap(u, v);
        irs.insert({u, v});
        rs.insert({u, v});
    }
    // 记录操作、关系记录 = 初始关系 - 淡忘关系
    for (int i = 0; i < q; i++) {
        scanf("%d%d%d", &op, &u, &v);
        u = dsz(u), v = dsz(v);
        if (u > v)swap(u, v);
        ops[i][0] = op, ops[i][1] = u, ops[i][2] = v;
        if (op == 1)rs.erase({u, v});
    }
    // 根据关系记录建立并查集
    for (auto &[a, b]: rs) unite(a, b);
    // 从前往后是删除关系,从后往前是添加关系
    bool r[q + 1];
    memset(r, 0, sizeof r);
    for (int i = q - 1; i >= 0; i--) {
        if (ops[i][0] == 2)r[i] = find(ops[i][1]) == find(ops[i][2]);
            // 初始为朋友关系的两人才能淡化朋友关系
        else if (irs.find({ops[i][1], ops[i][2]}) != irs.end())unite(ops[i][1], ops[i][2]);
    }
    // 输出结果
    for (int i = 0; i < q; i++) {
        if (ops[i][0] == 2)printf("%s\n", r[i] ? "Yes" : "no");
    }
    return 0;
}

时间复杂度: O ( m + q ) O(m+q) O(m+q)

空间复杂度: O ( m + q ) O(m+q) O(m+q)

小美的区间删除

题目描述

小美拿到了一个大小为 n n n 的数组,她希望删除一个区间后,使得剩余所有元素的乘积末尾至少有 k k k 0 0 0。小美想知道,一共有多少种不同的删除方案?

输入描述

第一行输入两个正整数 n , k n,k n,k

第二行输入 n n n 个正整数 a i a_i ai,代表小美拿到的数组。

  • 1 ≤ n , k ≤ 1 0 5 1\leq n,k \leq 10^5 1n,k105
  • 1 ≤ a i ≤ 1 0 9 1\leq a_i \leq 10^9 1ai109
输出描述

一个整数,代表删除的方案数。

解题思路

一个 2 2 2 和 一个 5 5 5 相乘可得到一个 0 0 0

代码实现
const int n = 1e5 + 5;

// s2[i] = a[1..i]中包含2的个数
// s5[i] = a[1..i]中包含5的个数
int s2[n], s5[n];

/**
 * 统计 x 中包含的 2 和 5 的个数
 */
pair<int, int> count25(int x) {
    int c2 = 0, c5 = 0;
    while (!(x & 1))c2++, x /= 2;
    while (x % 5 == 0)c5++, x /= 5;
    return {c2, c5};
}

int main() {
    int n, k, x;
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &x);
        auto [c2, c5] = count25(x);
        s2[i] = c2 + s2[i - 1], s5[i] = c5 + s5[i - 1];
    }
    int l, r;
    // 检查 l 和 r 是否不符合要求
    auto check = [&] {
        return s2[r] - s2[l - 1] > s2[n] - k || s5[r] - s5[l - 1] > s5[n] - k;
    };
    long long res = 0;
    // 枚举每类以 l 为左边界的区间
    for (l = 1; l <= n; l++) {
        // 找到以 l 为左边界且满足题目条件的最大区间
        int i = l, j = n;
        while (i < j) {
            r = (i + j + 1) >> 1;
            if (check())j = r - 1;
            else i = r;
        }
        r = i;
        // 若[l,r] 满足条件,则 [l,r-1] 也满足条件,类推
        if (!check())res += r - l + 1;
    }
    printf("%lld", res);
    return 0;
}

时间复杂度: O ( n l o g ( n ) ) O(nlog(n)) O(nlog(n))

空间复杂度: O ( n ) O(n) O(n)

END

文章文档:公众号 字节幺零二四 回复关键字可获取本文文档。

题目来源:美团2024年春招第一场笔试【技术】

文章声明:题目来源 牛客 平台,如有侵权,请联系删除!

  • 27
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
20233月11日,美团春季招聘笔试中共包含五道编程题目。以下是对每道题目的简要说明: 1. 题目一:这道题目要求解决一个数字统计的问题。可能涉及到的知识点包括数据结构、循环和条件判断等。解决问题的思路可能是使用字典等数据结构来保存统计结果,并使用循环逐个读取输入数据并进行统计。 2. 题目二:这道题目可能是一个字符串处理的问题。需要使用字符串的方法进行操作,如提取、拼接、查找和替换等。可能的解决思路包括使用正则表达式、切片和遍历等。 3. 题目三:这道题目可能涉及到算法和数据结构的知识。可能是一道涉及到数组、链表、树等数据结构的问题。解决思路可能包括遍历、递归、搜索和排序等。 4. 题目四:这道题目可能是一个动态规划的问题。需要根据给定的条件和规则,通过动态规划的方式求解问题。解决思路包括定义状态和转移方程,使用递推或记忆化搜索进行求解。 5. 题目五:这道题目可能是一个图论或网络问题。需要根据给定的图或网络结构,解决一个相关的问题。可能涉及到广度优先搜索、深度优先搜索、最短路径等知识。解决思路可能包括使用图或网络的相关算法进行求解。 以上只是对这五道编程题目的一些可能情况进行的简要描述,具体的题目内容可能会有所不同。希望这些信息能对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值