2026年苯环杯蓝桥模拟赛补题()
B 矩阵染色

暴力,当时没想出来要这么暴力()
先把所以符合条件的小块都存起来,然后三重循环开始遍历,确保三者不相等,然后检查两两中的坐标不重复,就计入答案。
#include <bits/stdc++.h>
using namespace std;
#define ull unsigned long long
#define int long long
#define pii array<int, 2>
#define endl "\n"
int a[6][6] = {
{11, 8, 3, 27, 24, 1}, {2, 21, 16, 35, 17, 4}, {9, 29, 20, 30, 5,
10},
{36, 33, 13, 6, 23, 7}, {31, 14, 15, 28, 12, 25}, {34, 19, 18, 37, 22,
39},
};
void solve() {
vector<array<pii, 2>> vt;
for (int x1 = 0; x1 < 6; x1++) {
for (int y1 = 0; y1 < 6; y1++) {
if (x1 != 5 && (a[x1][y1]+a[x1+1][y1])%2) {
vt.push_back({{{{x1, y1}}, {{x1+1, y1}}}});
}
if (y1 != 5 && (a[x1][y1]+a[x1][y1+1])%2) {
vt.push_back({{{{x1, y1}}, {{x1, y1+1}}}});
}
}
}
auto check = [&](array<pii, 2> X, array<pii, 2> Y) {
for (auto x : X) {
for (auto y : Y) if (x == y) return 1;
}
return 0;
};
int ans = 0;
int n = vt.size();
for (int i = 0; i < n; i++) {
for (int j = i+1; j < n; j++) {
if (check(vt[i], vt[j])) continue;
for (int k = j+1; k < n; k++) {
if (check(vt[i], vt[k])) continue;
if (check(vt[j], vt[k])) continue;
ans++;
}
}
}
cout << ans << endl;
}
F 好段计数

我们很容易得出他的暴力解法(),
同时可以注意到如果知道这个数左右第一个比他大的值,就可以用O(1) 的时间复杂度解决当前数会不会对答案产生贡献的问题了。
可以使用单调栈,如果当前值比栈顶大,那么一直弹出直到栈顶的值大于这个数,记录L[i]=这个数的下标;反之,将这个值入栈。
这样维护出任意一个值左边的第一个大值,同理右边的第一个大值也是一样的。
那么正向遍历这个数组,看看这个区间长度是否等于这个值就可以了。
难点:知道单调栈是啥,单调栈就是从栈顶到栈底一直递增的(或者递减)。
code
void solve()
{
cin >> n;
vi a(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
vi L(n + 1, 0), R(n + 1, n + 1);
stack<int> p;
for (int i = 1; i <= n; i++)
{
while (p.size() && a[i] > a[p.top()])
{
p.pop();
}
if (!p.empty())
{
L[i] = p.top();
}
p.push(i);
}
while (p.size())
{
p.pop();
}
for (int i = n; i >= 1; i--)
{
while (p.size() && a[i] > a[p.top()])
{
p.pop();
}
if (!p.empty())
{
R[i] = p.top();
}
p.push(i);
}
int ans = 0;
for (int i = 1; i <= n; i++)
{
int now = R[i] - L[i] - 1;
if (now == a[i])
{
ans++;
}
}
cout << ans << endl;
}
H 双机器人

你可以手模试一下,贪心显然不对的。
所以就可以考虑dp了,又因为n的数据范围也不大,支持O(n^2)的操作
dp先要找一下状态,发现也就俩状态,就是两个机器人的位置,然后发现如果遍历所有任务点,总会有一个机器人在i-1处,所以只要枚举另一个机器人的位置就行了,所以需要维护两个状态,dp[i][j],表示处理完第i个任务,一个机器人在i,一个在j。
code
void solve()
{
cin >> n;
vi a(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
a[0] = 0;
vvi dp(n + 1, vi(n + 1, 1e18));//求最小值,初始化为极大值
dp[1][0] = abs(a[1]);//显而易见
for (int i = 2; i <= n; i++)//因为i=1的情况已经预处理了,所以从i=2开始遍历
{
for (int j = 0; j < i - 1; j++)//j要小于i-1
{
//这个就表示一个机器人在i-1,一个机器人在j,使得i-1的机器人来到i,枚举j的位置
dp[i][j] = min(dp[i][j], dp[i - 1][j] + abs(a[i - 1] - a[i]));
//这个就表示一个机器人在i-1,一个机器人在j,让在j的机器人来到i,枚举j的位置
dp[i][i - 1] = min(dp[i][i - 1], dp[i - 1][j] + abs(a[i] - a[j]));
}
}
int mx = 1e18;
for (int i = 0; i < n; i++)
{
//到最后所有任务都结束了,一定是某一个在n点,另一个不知道在哪,所以枚举
mx = min(mx, dp[n][i]);
}
cout << mx << endl;
}
还没补完…………

浙公网安备 33010602011771号