
题目链接:https://codeforces.com/contest/2244
A - Iskander and Drawings
算是模拟题,我们直接暴力找出最大连续的子串再判断最长时间就可以了。我这里的实现思路是先判断有没有,没有直接输出返回,有就初始化最大长度为,然后遍历字符串找出最大连续的子串长度。最后根据最大长度计算出最大时间。(奇数除加偶数除)
#include <bits/stdc++.h>
using namespace std;using ll = long long;using ull = unsigned long long;#define endl '\n'#define mod 998244353typedef pair<ll, ll> pll;typedef pair<int, int> pii;
void solved() { int n; cin >> n; string s; cin >> s; int max_len = 1; int len = 1; bool f = false; for(int i = 0; i < n;i++) if(s[i] == '#') f = true; if(!f) {cout << 0 << endl; return;} for(int i = 1; i < n;i++){ if(s[i - 1] == '#' && s[i] == '#') len++; else len = 1; max_len = max(max_len, len); } cout << ((max_len % 2) ? max_len / 2 + 1 : max_len / 2) << endl;}
int main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); int _ = 1; cin >> _; while (_--) { solved(); } return 0;}B - Nikita and Books
这题我们根据题意可以知道,对应一个数,使其满足严格单调递增的数组,至少需要这样的排列。也就是数组元素之和要至少大于等于 。(第一个条件)我们可以发现大于等于这个值的数无论如何都能构造出一个满足条件的数组。
然后我们再注意到题目的另外一个关键条件:书本的传递是只能从左向右的。这其实说明一个情况,如果前项的和无法满足大于,(第二个条件)那么整个数组也就无法严格单调递增了,所以最终能满足条件的数组必须要满足这两个条件。(实际上第二个条件也就是第一条件的严苛版)
我们在实现时就在遍历时就判断当前的前缀和是否大于等于即可。(这里我在实现时还复杂了些,第一处特判的部分可以删去。)
#include <bits/stdc++.h>
using namespace std;using ll = long long;using ull = unsigned long long;#define endl '\n'#define mod 998244353typedef pair<ll, ll> pll;typedef pair<int, int> pii;
int a[200010];
void solved() { int n; cin >> n;
ll sum = 0, pre = 0; ll cmp = n * (1 + n) / 2; for(int i = 1; i <= n;i++){ cin >> a[i]; sum += a[i]; } if(sum < cmp){cout << "NO" << endl; return;}
sum = 0; for(int i = 1; i <= n;i++){ pre += a[i]; sum += i; if(pre < sum){ cout << "NO" << endl; return; } } cout << "YES" << endl;}
int main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); int _ = 1; cin >> _; while (_--) { solved(); } return 0;}C - Stepan and Permutation
这题我们可以转化一下题意,实际上能交换的两个元素就是需要满足两者之间的距离为或者就可以交换了。这里我们还需要理解的就是这个条件还可以转化得更加细一些:只要满足距离(最大公因数)的两个元素都可以交换元素,这个是很显而易见的,因为我们完全可以通过两个或者更多次操作实现这个更短距离的交换。
因此,根据这个最短交换距离,我们可以判断一个元素最终是否能回到它作为排列的位置。也就是需要他当前的位置和之差要是的倍数(或者就已经在原位了),那么它就是可达的,否则就不可达。所以我们就只需要判断这个条件即可,如果存在和不满足这个条件就直接输出,都满足就输出。
#include <bits/stdc++.h>
using namespace std;using ll = long long;using ull = unsigned long long;#define endl '\n'#define mod 998244353typedef pair<ll, ll> pll;typedef pair<int, int> pii;
int p[200010];
void solved() { int n, x, y; cin >> n >> x >> y; for(int i = 1; i <= n;i++) cin >> p[i];
int g = gcd(x, y); for (int i = 1; i <= n; i++) { if ((p[i] - i) % g != 0) { cout << "NO" << endl; return; } } cout << "YES" << endl;}
int main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); int _ = 1; cin >> _; while (_--) { solved(); } return 0;}D - Yaroslav and Productivity
这题我们不妨以作为边界划分每个区间:。那么我们就会发现,每个区间的和只有两种状态,要么是正要么是负。除了最后一个区间我们无法翻转操作之外,其他区间我们都希望尽可能取到正。(因为我们需要找出一种操作所有元素之和的最大值最大)
而事实上,我们完全可以做到让所有的区间为正。我们不妨从最右边的区间开始,它的正反只由决定,所以我们一定可以让它取得正。我们假设翻转了前项的所有区间定义,反则设置为。然后看到,它的正反会受到和的共同影响,但我们完全可以根据已经设定好的适当调整使得这个区间也取到正:
假设需要翻转才能取到正那么,并且不需要翻转才能取到正那么,这样才能抵消的翻转。因此后面这两个区间的状态对前面区间的操作的影响其实是也就是没翻转前面的个区间的。所以传递给前面的状态就是重赋值为(未翻转前面的区间),那么就可以再根据这个来判断是否需要翻转。
以此类推前面的区间的,同样可以根据后面传递上来的的状态来取或,使得最终每个区间都取到正。
所以我们最终的实现只需要将这些划分的区间的正值相加,再加上最后一段无法操作的区间的原值即是最终答案了。
#include <bits/stdc++.h>
using namespace std;using ll = long long;using ull = unsigned long long;#define endl '\n'#define mod 998244353typedef pair<ll, ll> pll;typedef pair<int, int> pii;
void solved() { int n, m; cin >> n >> m;
vector<ll> prefix(n + 1, 0); for(int i = 1; i <= n;i++){ ll x; cin >> x; prefix[i] = prefix[i - 1] + x; }
vector<int> b(m, 0); for(int i = 0; i < m;i++) cin >> b[i]; sort(b.begin(), b.end());
ll ans = 0; int last_end = 0; for(int it : b){ ll sum = prefix[it] - prefix[last_end]; last_end = it; ans += abs(sum); } ans += prefix[n] - prefix[last_end]; cout << ans << endl;}
int main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); int _ = 1; cin >> _; while (_--) { solved(); } return 0;}