A. Blackboard List
题目大意
起初黑板上有两个数,现在不断选取两个数作出他们俩差的绝对值并写在黑板上,如此往复直到黑板上有 \(n\) 个数。现在给定这 \(n\) 个数,问起初两数的其中一个数是多少。
解题思路
我们分两种可能:要么这两个数有负数,要么没有。
- 有负数的情况,因为每次写下的都是绝对值,那么这些数中的负数一定是起初两数之一。
- 没有负数的情况,没有负数可以保证每次的差值一定比原来两数的最大值要小,因为最小情况下也是减去 \(0\),得到的结果不会比原数大。那么全部数的最大值就是原来两数的最大值。
AC Code
#include <iostream>
#include <algorithm>
#include <cstring>
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
const int MOD = 1e9 + 7;
void solve() {
LL n, x;
cin >> n;
LL min_ = 0x3f3f3f3f, max_ = -0x3f3f3f3f;
for (int i = 1; i <= n; ++i) {
cin >> x;
min_ = min(min_, x);
max_ = max(max_, x);
}
cout << (min_ < 0 ? min_ : max_) << endl;
}
signed main() {
ios;
int T = 1;
cin >> T;
while (T--) {
solve();
}
}
B. Minimize Permutation Subarrays
题目大意
给定 \(1\sim n\) 的一个排列,现在我们只允许做一次交换,使得交换后的排列的所有子数列中的排列数最少。
这里排列指的是数组中恰好有 \(1,2,\dots,subarray.\text{length}\) 这些数.
解题思路
我们的排列一定是 \(1, 2,\dots\) 这样的,我们只需要阻断 \(1\) 和 \(2\),并且塞进去最不可能出现在这里元素 \(n\) 即可。这时我们的子数组中的排列就只有两个,单独的 \(1\) 和整个排列。
AC Code
#include <iostream>
#include <algorithm>
#include <cstring>
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
const int MOD = 998244353;
int a[N];
void solve() {
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
int x;
cin >> x;
a[x] = i;
}
if ((a[n] - a[1]) * (a[n] - a[2]) < 0) {
cout << 1 << ' ' << 1 << endl;
} else if (a[n] > a[1] && a[n] > a[2]) {
cout << a[n] << ' ' << max(a[1], a[2]) << endl;
} else {
cout << a[n] << ' ' << min(a[1], a[2]) << endl;
}
}
signed main() {
ios;
int T = 1;
cin >> T;
while (T--) {
solve();
}
}
C. No Prime Differences
题目大意
需要构造一个 \(n\times m\) 的矩阵,需要满足其中的元素恰好为 \(1\sim nm\),同时任意相邻两项的差的绝对值不为质数。
解题思路
相邻两项无非就是横着俩以及竖着俩都满足差值不是质数。我们可以考虑构造差值满足以下关系:
- 差值为 \(1\)。
- 差值为 \(2\) 的非一次倍。
- 差值为 \(n\) 的整数倍。
如果 \(n\) 是偶数的话,那么很容易看出来,只需要按照如下情形即可:
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
如果 \(n\) 是奇数的话,我们可以调换输出顺序,把偶数行先输出,奇数行后输出:
6 7 8 9 10
16 17 18 19 20
1 2 3 4 5
11 12 13 14 15
奇数行和偶数行内部满足上面对 \(n\) 为偶数情况的讨论,两者交界处的差值是 \(n\) 的整数倍非质数,故可如此构造。
AC Code
#include <iostream>
#include <algorithm>
#include <cstring>
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
const int MOD = 998244353;
void solve() {
int n, m;
cin >> n >> m;
for (int i = 1; i < n; i += 2) {
for (int j = 1; j <= m; ++j) {
cout << i * m + j << ' ';
}
cout << endl;
}
for (int i = 0; i < n; i += 2) {
for (int j = 1; j <= m; ++j) {
cout << i * m + j << ' ';
}
cout << endl;
}
cout << endl;
}
signed main() {
ios;
int T = 1;
cin >> T;
while (T--) {
solve();
}
}
D. Bracket Walk
题目大意
给定一个括号序列,起初时人站在第一个字符上面,每次可以向左或者向右走。同时给定 \(q\) 个询问,每次询问会将括号序列第 \(x\) 个括号倒转方向,问能否使得走到的字符拼接起来成为一个匹配的括号序列。
解题思路
首先确定一定不可能的情况,我们向左走一次,就必须向右走回来,所以最终步数的奇偶性和 \(n\) 一致,所以 \(n\) 为奇数的时候肯定不能组成匹配的括号序列。
我们考虑原串已经含有了 ()
,那么可以直接走过这两个字符,如果出现不匹配部分,我们就将多走一次少的那种括号,我们期望获得 ()()
这样的括号序列,那么可以记录有多少括号不满足这一条,存到我们的set中,随后针对翻转修改,我们通过修改set的元素就可以达到组件的删改,最后只需要判断set的头元素和尾元素,实际上就是最大最小值的奇偶关系即可。
AC Code
#include <iostream>
#include <algorithm>
#include <cstring>
#include <set>
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
const int MOD = 998244353;
set<LL> st;
void solve() {
int n, m;
cin >> n >> m;
string s;
cin >> s;
for (int i = 0; i < n; ++i) {
if (s[i] == (i & 1 ? '(' : ')')) {
st.insert(i + 1);
}
}
while (m--) {
int x;
cin >> x;
if (st.contains(x)) {
st.erase(x);
} else {
st.insert(x);
}
cout << (n & 1 || (!st.empty() && (*st.begin() & 1 || !(*st.rbegin() & 1))) ? "NO" : "YES") << endl;
}
}
signed main() {
ios;
int T = 1;
// cin >> T;
while (T--) {
solve();
}
}
标签:const,cout,int,题解,nullptr,cin,877,Div.2,include
From: https://www.cnblogs.com/SanCai-Newbie/p/17475808.html