知能科技 软件开发 笔试
随便投的一个公司,发现居然也要在牛客上笔试
A. cf原题
https://codeforces.com/contest/1802/problem/B
#include<bits/stdc++.h>
int A[100005];
void solve() {
int n;
std::cin >> n;
for (int i = 1; i <= n; i++) {
std::cin >> A[i];
}
int x = 0, y = 0, unknown = 0, pre = 0, ans = 0;
for (int i = 1; i <= n; i++) {
if (A[i] == 1) {
++unknown;
} else if (A[i] == 2) {
pre += unknown;
unknown = 0;
}
std::cerr << i << ' ' << ans << ' ' << unknown << ' ' << pre << ' ' << unknown + pre / 2 + 1 << '\n';
if (pre) {
ans = std::max(ans, unknown + pre / 2 + 1);
} else {
ans = std::max(ans, unknown);
}
}
std::cout << ans << '\n';
}
int main() {
std::cin.tie(nullptr) -> sync_with_stdio(false);
int T = 1;
//std::cin >> T;
while (T--) {
solve();
}
return 0;
}
B. 构造题
定义美丽值为矩阵相邻数字的绝对值大小种类,例如:
[1 2
4 3]
有|1 - 4| = 3, |1 - 2| = 1, |2 - 3| = 1, |4 - 3| = 1, 有两种。
给定一个n <= 150, 构造 n * n矩阵使得美丽值最大。
构造思路:
n为奇数:
1, n, 2, n - 1, 3
n -2, 4, n - 3....
..........
n为偶数:
1, n, 2, n - 1, 3
....n - 3, 4, n - 2
...................
不难看出这样构造是可以达到最优值的。
#include<bits/stdc++.h>
int A[2222][2222];
int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
int n;
void solve(int cas) {
std::cin >> n;
if (n == 2) {
std::cout << "1 3\n4 2\n";
return ;
}
if ((n & 1)) {
int flag = 0;
int x = 1, y = n * n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (!flag) {
A[i][j] = x++;
} else {
A[i][j] = y--;
}
flag ^= 1;
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
std::cout << A[i][j] << " \n"[j == n];
}
}
} else {
std::map<int, int> mp;
int flag = 1;
int x = 1, y = n * n;
for (int i = 1; i <= n; i++) {
if (i & 1) {
for (int j = 1; j <= n; j++) {
if (!flag) {
A[i][j] = x++;
} else {
A[i][j] = y--;
}
flag ^= 1;
}
} else {
for (int j = n; j >= 1; j--) {
if (!flag) {
A[i][j] = x++;
} else {
A[i][j] = y--;
}
flag ^= 1;
}
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
std::cout << A[i][j] << " \n"[j == n];
}
}
}
}
void solve() {
// std::cin >> n;
// for (int i = 1; i <= n; i++) {
// for (int j = 1; j <= n; j++) {
// std::cin >> A[i][j];
// }
// }
std::set<int> st;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
for (int k = 0; k < 4; k++) {
int nx = i + dir[k][0], ny = j + dir[k][1];
if (nx >= 1 and ny >= 1 and nx <= n and ny <= n) {
st.emplace(std::abs(A[i][j] - A[nx][ny]));
//std::cerr << i << ' ' << j << ' ' << A[i][j] << ' ' << A[nx][ny] << '\n';
}
}
}
}
std::cerr << "debug: " << st.size() << '\n';
}
int main() {
std::cin.tie(nullptr) -> sync_with_stdio(false);
int T = 1;
//std::cin >> T;
while (T--) {
solve(T);
solve();
}
return 0;
}
附加题:求一个长度为n(n <= 200000) 的序列中,长度不小于k的最大中位数,只需要给出思路
思路:二分答案,原数组可以转化成-1,1,那么求一个前缀和,对于每个位置 i,我都考查一下 [1, i - k + 1] 中是否存在一个Sum[j],使得 Sum[i] - Sum[j] >= 0 即可,这个可以维护前缀最小值去实现。
时间复杂度 O(nlogn), 空间复杂度 O(n)。

查看7道真题和解析