目录
本次比赛的链接:
2023河南萌新联赛第(一)场:河南农业大学_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ
E:动物朋友(双指针)
思路:我们可以记录快指针和慢指针之间的快乐值,若此快乐值小于所需快乐值,则让快指针++,若此快乐值大于所需快乐值则让慢指针++,快乐值相等则方案数加一
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int mod = 1e9 + 7;
void solve() {
int i, j, k, n, m;
cin >> n >> m;
vector<int>nums(n, 0);
for (i = 0; i < n; i++) {
cin >> nums[i];
}
int left = 0, right = 0;
int cnt = 0, ans = 0;
for (right = 0; right < n; right++) {
cnt += nums[right];
while (left <= right && cnt > m) {
cnt -= nums[left];
left++;
}
if (cnt == m) ans++;
}
cout << ans << endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int t;
t = 1;
while (t--) {
solve();
}
system("pause");
return 0;
}
F:松鼠排序(并查集)
思路:对于每个nums[i]与i不相等的位置,在并查集中把a[i]和i两个点合并,然后查看有几个集合,最终答案为每个集合块的大小减一的和,即ans = ∑(size - 1),例如假设其中一个块为3 1 2,我们要将其变为1 2 3,此时size = 3,只需交换两次即可完成排序
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int mod = 1e9 + 7;
vector<int>fa;
void init(int n) {
fa.resize(n + 1, 0);
for (int i = 0; i < fa.size(); i++) {
fa[i] = i;
}
}
int find(int x) {
if (fa[x] == x) return x;
return fa[x] = find(fa[x]);
}
void setunion(int a, int b) {
int x = find(fa[a]);
int y = find(fa[b]);
if (x != y) fa[x] = y;
}
void solve() {
int i, j, k, n;
cin >> n;
vector<int>nums(n, 0);
init(n);
for (i = 0; i < n; i++) {
cin >> nums[i];
}
for (i = 0; i < n; i++) {
if (nums[i] != i + 1) {
setunion(nums[i], i + 1);
}
}
map<int, int>mp;
for (i = 1; i <= n; i++) {
mp[find(fa[i])]++;
}
ll ans = 0;
for (auto [x, y] : mp) {
ans += y - 1;
}
cout << ans << endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int t;
t = 1;
while (t--) {
solve();
}
system("pause");
return 0;
}
G:Reverse(思维)
思路:通过观察我们可以发现,反转后的最长连续1的串为此01串中最大连续1的字串和次大连续1的字串和,所以我们将这两部分加起来即为最终答案
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int mod = 1e9 + 7;
void solve() {
int i, j, k, n;
cin >> n;
string s;
cin >> s;
vector<int>nums;
for (i = 0; i < s.length(); i++) {
int cnt = 0;
bool flag = false;
while (s[i] == '1') {
flag = true;
i++;
cnt++;
}
if (flag) i--;
if (cnt != 0) nums.push_back(cnt);
}
ll ans = 0;
sort(nums.begin(), nums.end(), greater<int>());
for (i = 0; i < 2 && i < nums.size(); i++) {
ans += nums[i];
}
cout << ans << endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int t;
t = 1;
while (t--) {
solve();
}
system("pause");
return 0;
}
H:迷宫探险(最短路)
思路:本题难点在于建图,对于此迷宫,我们可以从左至右,从上至下对其进行1 ~ n * m进行编号,根据题意,在弹射器上弹射不消耗时间,而正常移动消耗1单位时间,则我们可以建图,对于每个 ‘.’ ,若周围四个方向合法,它向相邻四个单位建边的边权为1,对于每个‘*’,若周围四个方向合法,则它向距离它相应距离的四个点单位建边的边权为0,对于‘#’则不建边,然后对所建图跑一边最短路即可,时间复杂度为O(k * log(n * m))
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int mod = 1e9 + 7;
typedef struct {
int v, w;
}edge;
vector<pii>dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
vector<vector<edge>>G(500005);
vector<bool>visit;
vector<ll>dist;
int n, m;
void dijkstra(int s) {
int len = n * m;
dist.resize(len + 1, INT_MAX);
visit.resize(len + 1, false);
dist[s] = 0;
priority_queue<pii>Q;
Q.push({0, s});
while (!Q.empty()) {
auto t = Q.top();
Q.pop();
int u = t.second;
if (visit[u]) continue;
visit[u] = true;
for (auto ed : G[u]) {
int v = ed.v, w = ed.w;
if (dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
Q.push({-dist[v], v});
}
}
}
}
void solve() {
int i, j, k;
cin >> n >> m;
vector<vector<int>>laby(n + 1, vector<int>(m + 1, 0));
for (i = 0; i < n; i++) {
string s;
cin >> s;
for (j = 0; j < s.length(); j++) {
if (s[j] == '#') laby[i + 1][j + 1] = -1;
else laby[i + 1][j + 1] = 0;
}
}
cin >> k;
for (i = 0; i < k; i++) {
int a, b, c;
cin >> a >> b >> c;
laby[a][b] = c;
}
for (i = 1; i <= n; i++) {
for (j = 1; j <= m; j++) {
if (laby[i][j] > 0) {
int new_x, new_y;
new_x = i - laby[i][j];
if (new_x >= 1 && laby[new_x][j] != -1) G[(i - 1) * m + j].push_back({(new_x - 1) * m + j, 0});
new_x = i + laby[i][j];
if (new_x <= n && laby[new_x][j] != -1) G[(i - 1) * m + j].push_back({(new_x - 1) * m + j, 0});
new_y = j - laby[i][j];
if (new_y >= 1 && laby[i][new_y] != -1) G[(i - 1) * m + j].push_back({(i - 1) * m + new_y, 0});
new_y = j + laby[i][j];
if (new_y <= m && laby[i][new_y] != -1) G[(i - 1) * m + j].push_back({(i - 1) * m + new_y, 0});
} else if (laby[i][j] == 0) {
int new_x, new_y;
for (auto dir : dirs) {
new_x = i + dir.first;
new_y = j + dir.second;
if (new_x >= 1 && new_x <= n && new_y >= 1 && new_y <= m && laby[new_x][new_y] != -1) {
G[(i - 1) * m + j].push_back({(new_x - 1) * m + new_y, 1});
}
}
}
}
}
dijkstra(1);
if (dist[n * m] == INT_MAX) cout << -1 << endl;
else cout << dist[n * m] << endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int t;
t = 1;
while (t--) {
solve();
}
system("pause");
return 0;
}
J:合唱比赛(模拟)
思路:依题意进行模拟即可
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int mod = 1e9 + 7;
void solve() {
int i, j, k, n;
cin >> n;
vector<int>nums1(n, 0);
for (i = 0; i < n; i++) {
cin >> nums1[i];
}
vector<int>nums2(nums1);
nums1.push_back(1);
sort(nums1.begin(), nums1.end());
nums2.push_back(100);
sort(nums2.begin(), nums2.end());
double res1 = 0;
double res2 = 0;
for (i = 1; i < nums1.size() - 1; i++) {
res1 += nums1[i];
res2 += nums2[i];
}
res1 = res1 * 1.0 / (n - 1);
res2 = res2 * 1.0 / (n - 1);
printf("%.6lf %.6lf", res1, res2);
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int t;
t = 1;
while (t--) {
solve();
}
system("pause");
return 0;
}
K:以撒和隐藏房间(暴力枚举)
思路:依题意对每个格子进行枚举判断即可
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int mod = 1e9 + 7;
vector<string>G;
vector<pii>dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
int n, m;
bool judje(int x, int y) {
int new_x, new_y;
int ans = 0;
for (auto dir : dirs) {
new_x = x + dir.first;
new_y = y + dir.second;
if (new_x >= 0 && new_x < n && new_y >= 0 && new_y < m) {
if (G[new_x][new_y] == '2') return false;
if (G[new_x][new_y] == '1') ans++;
}
}
if (ans == 3) return true;
return false;
}
void solve() {
int i, j, k;
cin >> n >> m;
G.resize(n);
for (i = 0; i < n; i++) {
cin >> G[i];
}
ll ans = 0;
for (i = 0; i < n; i++) {
for (j = 0; j < m; j++) {
if (G[i][j] == '0' && judje(i, j)) ans++;
}
}
if (ans > 0) {
cout << "YES" << endl;
cout << ans << endl;
} else {
cout << "NO" << endl;
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int t;
t = 1;
while (t--) {
solve();
}
system("pause");
return 0;
}