淘天笔试 淘天笔试题 0329
笔试时间:2025年03月29日
历史笔试传送门:
第一题
题目:合并代价
小红拿到一个长度为n的数组,下标从1开始。定义一次合井操作为:选定任意的两个相邻的元素ai和ai+1,将它们合并成一个数,其余元素按照原有顺序从前到后依次拼接。这个数等于ai和ai+1的最大值,数组长度减少1。
例如a=[1,2,3,4,5],小红可以选定a2和a3,合并成3,数组变为[1,3,4,5],花费代价3。在执行上述的合并操作前,小红可以选择任意两个元索,将它们交换任意次(也可以不交换)。求解,执行恰好n-1轮"合并"操作,使得将数组合并的只剩一个数,最少需要花费多少代价?
输入描述
第一行输入一个整数n,表示数组长度。
第二行输入n个整数a1,a2,..an代表数组元素。
输出描述
输出一个整数,表示最小花费。
样例输入
3
3 2 1
样例输出
5
说明:
在这个样例中,有两种直接合并的方法:
1、先合并3,2,花费max{3,2}=3;再合井{3,1},花费max{3,1}=3,总花费6。
2、先合并2,1,花费max{2,1}=1;再合幷{3,2},花费max{3,2}=3,总花费5。
然而,不要忘记了,在开始前。我们还可以进行交换操作。然而,可以证明,再怎么交换也不会存在比5更小的答案。
参考题解
由于可以在操作之前进行任意次交换,那么问题其实就转化成了类似哈夫曼树问题。用一个优先队列维护所有元素,每次取出最小的两个数,把他们中较大的那个重新入队并加到答案中,直到只剩最后一个数。
C++:[此代码未进行大量数据的测试,仅供参考]
#include <bits/stdc++.h> usingnamespacestd; using ll = longlong; int main() { int n; cin >> n; vector<ll> a(n); for (int i = 0; i < n; ++i) { cin >> a[i]; } priority_queue<ll, vector<ll>, greater<ll>> q; for (auto& x : a) { q.push(x); } ll res = 0; while (q.size() > 1) { ll x = q.top(); q.pop(); ll y = q.top(); q.pop(); res += max(x, y); q.push(max(x, y)); } cout << res << endl; }
Java:[此代码未进行大量数据的测试,仅供参考]
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); long[] a = new long[n]; for (int i = 0; i < n; i++) { a[i] = sc.nextLong(); } PriorityQueue<Long> q = new PriorityQueue<>(Comparator.naturalOrder()); for (long x : a) { q.add(x); } long res = 0; while (q.size() > 1) { long x = q.poll(); long y = q.poll(); res += Math.max(x, y); q.add(Math.max(x, y)); } System.out.println(res); } }
Python:[此代码未进行大量数据的测试,仅供参考]
import heapq def main(): n = int(input()) a = list(map(int, input().split())) q = [] for x in a: heapq.heappush(q, x) res = 0 while len(q) > 1: x = heapq.heappop(q) y = heapq.heappop(q) res += max(x, y) heapq.heappush(q, max(x, y)) print(res) if __name__ == "__main__": main()
第二题
题目:最少修改次数
小苯有一个长度为n的01串x(下标从1到n),巧合的是格格也有一个长度恰好为n-1的01串y。(下标从1到n-1)
据说,格格的字符串y是用来匹配小菜的字符串x的,具体来说:
如果yi = 1 (1 ≤ i ≤ n - 1),则意味着必须有:xi ≠ xi+1
如果yi = 0 (1 ≤ i ≤ n - 1),则意味着必须有:xi = xi+1
而现在小菜的串并不一定满足y串的匹配要求,因此格格希望小菜修改尽可能少的字符,使得匹配成立,调你帮小菜算一算至少需要修改多少个字符吧。
修改:选择i (1 ≤ i ≤ n),执行:xi := xi ⊕ 1。(其中⊕表示按位异或或运算。)
输入描述
每个测试文件均包含多组测试数据。第一行输入一个整数T (1 ≤ T ≤ 100) 代表数据组数,
每组测试数据描述如下:第一行输入一个正整数n (2 ≤ n ≤ 10^6) 代表x串的长度。
第二行输入一个长度为n,仅由字符'0'和'1'构成的字符串x。
第三行输入一个长度为n-1,仅由字符'0'和'1'构成的字符串y。
除此之外,保证单个测试文件的n之和不超过10^6。
输出描述
对于每组测试数据在单独的一行输出一个整数,表示最少的修改次数。
样例输入
2
8
11001011
1000111
6
101010
11111
样例输出
4
0
说明:
对于第一组测试数据,我们修改x串为"10000101"即可,需要至少4次修改操作。
对于第二组测试数据,我们不需要修改x,因此输出0即可。
参考题解
除第一个位置外,x的每一项都受到y对应位置的影响。确切来说只要决定了x的第一位,那么后面的所有位置都能依次确定。因此做法就是枚举x的第一位是0还是1,进而计算出总花费,两种情况取最小即可。
C++:[此代码未进行大量数据的测试,仅供参考]
#include <bits/stdc++.h> usingnamespacestd; int calc(vector<int> x, string& y, int st) { int res = 0; int n = y.size(); if (x[0] != st) { res++; x[0] ^= 1; } for (int i = 0; i < n; i++) { if (y[i] == '1') { if (x[i + 1] == x[i]) { x[i + 1] ^= 1; res++; } } else { if (x[i + 1] != x[i]) { x[i + 1] ^= 1; res++; } } } return res; } int main() { int t; cin >> t; while (t--) { int n; cin >> n; string z, y; cin >> z >> y; vector<int> x; for (char ch : z) {
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南