CF Round 771 Div2 题解

A题 Reverse

给定一个长度为 n 的排列,我们可以选择将其中一个区间反转,问怎样反转可以使得这个新排列的字典序最小,并输出这个最小的字典序。

1n500

如果字典序已经最小,那么就不管他。

假设区间 [1,l1] 上面的数都在合适的位置上,而 pll,那么我们直接找到后面等于 l 的位置,下标记为 r,然后反转区间 [l,r] 即可。

#include<bits/stdc++.h> using namespace std; const int N = 510; int n, p[N]; void solve() { cin >> n; for (int i = 1; i <= n; ++i) cin >> p[i]; for (int i = 1; i <= n; ++i) if (p[i] != i) { int l = i, r; for (int j = n; j > i; j--) if (p[j] == i) { r = j; break; } reverse(p + l, p + r + 1); break; } for (int j = 1; j <= n; ++j) cout << p[j] << " "; cout << endl; } int main() { int T; cin >> T; while (T--) solve(); return 0; }

B题 Odd Swap Sort (构造)

给定一个长度为 n 的数列 {an}。如果两个相邻元素之和为奇数,那么我们就可以将其进行交换。问我们能否通过若干次操作将这个数列变为单调不降?

1n105,1ai109

一个不是很直观的冷知识:如果两个数都是奇数(偶数),那么他们的相对位置不会产生变化(他俩不可能交换顺序)。

所以我们直接按照奇偶,按顺序将原数组分成两个,如果两个数组均单调不降,那么最后这个数组也是可以通过交换而变为单调不降的。

#include<bits/stdc++.h> using namespace std; int n; vector<int> vec[2]; bool solve() { vec[0].clear(), vec[1].clear(); cin >> n; for (int i = 1; i <= n; ++i) { int x; cin >> x; vec[x % 2].push_back(x); } for (int x = 0; x < 2; ++x) { vector<int> &v = vec[x]; for (int i = 1; i < v.size(); ++i) if (v[i - 1] > v[i]) return false; } return true; } int main() { int T; cin >> T; while (T--) puts(solve() ? "Yes" : "No"); return 0; }

C题 Inversion Graph(图,数学,数据结构)

给定一个长度为 n 的排列 {pn},我们将依照此排列来建立一个图:

图起初有 n 个孤立点,倘若存在逆序对 (i,j),则在这两个点之间连一条边。

图建立完毕后,问这个图的连通块的数量是多少。

n105

有一个并不显然的性质:倘若存在逆序对 [l,r],那么整个区间内的点都在一个连通块内。

证明:我们记 pl=x,pr=y,pi=z(l<i<r),那么:

  1. z<x 时,有 pl>pi,l<i,i 和 l 之间连边
  2. z>x 时,有 pi>pr,i<r,i 和 r 之间连边

又因为 l 和 r 之间存在边,所以整个区间 [l,r] 都在一个连通块内。

那么,我们将最后的连通块按照形成顺序排序,那么他们显然是一个升序,这一流程类似单调栈,所以我们用栈来维护。

我们记栈顶为 x(空则为 0),新点的值为 y,如果 y>x 则直接推进去,反之则一直从栈顶 pop,直到栈顶元素小于 y,然后将 x 推进去。

#include<bits/stdc++.h> using namespace std; const int N = 100010; int n, a[N]; int solve() { cin >> n; for (int i = 1; i <= n; ++i) cin >> a[i]; stack<int> s; for (int i = 1; i <= n; ++i) { int x = s.empty() ? 0 : s.top(); while (!s.empty() && s.top() > a[i]) s.pop(); s.push(max(a[i], x)); } return s.size(); } int main() { int T; cin >> T; while (T--) cout << solve() << endl; return 0; }

D题 Big Brush(BFS,构造)

给定一张 nm 的格子图,现在我们可以进行若干次操作,每次操作选定一个坐标 (x,y) 和一个颜色 c,然后将 (x,y),(x+1,y),(x,y+1),(x+1,y+1) 全部涂上 c

现在给定一张已经涂好色的地图,问我们能否构造出我们的操作顺序(至多进行 nm 次操作)?不能则输出 -1。

2n,m103,1ainm

我们首先将地图上可以直接进行操作的那几块进行操作,然后将他们标记上 0。

随后,我们地图上不停找点,如果这个点可进行操作(且有必要进行操作),那么下一次就对他进行操作。

暴力寻找是不可取的(电脑不像人眼一样能一眼看出来),但是每次将一个块操作完之后,我们只考虑其周围的八个点,并考虑下一步对他们进行操作。这个 FIFO 的模式,我们肯定写一个队列来处理。

考虑到操作的次数限制,加上避免死循环,所以额外开一个 vis 数组来标记,避免某个点重复进入队列。

总复杂度 O(nm),不过自带大常数,需要花心思优化。

#include<bits/stdc++.h> using namespace std; const int N = 1010; int n, m, a[N][N], vis[N][N]; inline bool can(int i, int j) { return i >= 1 && i < n && j >= 1 && j < m; } int check1(int x, int y) { return a[x][y] == a[x][y + 1] && a[x][y] == a[x + 1][y] && a[x][y] == a[x + 1][y + 1]; } int check2(int x, int y) { if (!can(x, y)) return 0; set<int> s; for (int i = 0; i < 2; ++i) for (int j = 0; j < 2; ++j) if (a[x + i][y + j]) s.insert(a[x + i][y + j]); return s.size() == 1 ? *s.begin() : 0; } void update(int x, int y) { for (int i = 0; i < 2; ++i) for (int j = 0; j < 2; ++j) a[x + i][y + j] = 0; } struct Node { int x, y, c; }; queue<Node> q; stack<Node> ans; int main() { //read cin >> n >> m; for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) cin >> a[i][j]; //solve for (int i = 1; i < n; ++i) for (int j = 1; j < m; ++j) if (check1(i, j)) { vis[i][j] = 1; Node t = (Node){i, j, a[i][j]}; q.push(t), ans.push(t); } while (!q.empty()) { int x = q.front().x, y = q.front().y; q.pop(); update(x, y); for (int i = -1; i <= 1; ++i) for (int j = -1; j <= 1; ++j) { int v = check2(x + i, y + j); if (v && !vis[x + i][y + j]) { vis[x + i][y + j] = 1; Node t = (Node){x + i, y + j, v}; q.push(t), ans.push(t); } } } //output int res = 0; for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) if (!a[i][j]) ++res; if (res != n * m) puts("-1"); else { cout << ans.size() << endl; while (!ans.empty()) { Node t = ans.top(); printf("%d %d %d\n", t.x, t.y, t.c); ans.pop(); } } return 0; }

__EOF__

本文作者cyhforlight
本文链接https://www.cnblogs.com/cyhforlight/p/15963366.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   cyhforlight  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示