Codeforces Round #826 (Div. 3) A - E
A
照着题意$if \ else $即可。
void solve() {
string s1, s2; cin >> s1 >> s2;
int n = sz(s1), m = sz(s2);
if (s1 == s2) cout << '=' << endl;
else {
if (s1[n - 1] > s2[m - 1]) cout << '<' << endl;
else if (s2[m - 1] > s1[n - 1]) cout << '>' << endl;
else if (s1[n - 1] == 'S'){
if (n > m) cout << "<" <<endl;
else if (n < m) cout << ">" << endl;
else cout << "=\n";
}
else if (s1[n - 1] == 'L'){
if (n > m) cout << ">" <<endl;
else if (n < m) cout << "<" << endl;
else cout << "=\n";
}
}
}
B
除\(n=3\)之外,可以把数组分为长度大于\(n/2\)和小于\(n/2\)的前后两段,调换顺序输出。
void solve() {
int n; cin >> n;
if (n == 3) cout << -1 << endl;
else {
int mid = n / 2 + 1;
for (int i = mid;i <= n;i++) cout << i << ' ';
for (int i = 1;i < mid;i++) cout << i << ' ';
cout << endl;
}
}
C
可以枚举第一段的和为多少,然后双指针做后面的分段,时间复杂度\(O(n^2)\),赛时写了个先枚举最大段长度,再枚举第一段长度的,好像是个\(O(n^3)\),但跑得很快过了。
void solve() {
int n; cin >> n;
vector<int> a(n + 1), sum(n + 1);
for (int i = 1;i <= n;i++) {
cin >> a[i];
sum[i] = sum[i - 1] + a[i];
}
for (int len = 1;len <= n;len ++) {
bool ok = false;
for (int i = 1;i <= len;i++) {
int res = sum[i];
for (int l = i + 1, r = i + 1;l <= n;l ++) {
while (sum[r] - sum[l - 1] < res && r - l + 1 <= len) r ++;
if (sum[r] - sum[l - 1] != res || r - l + 1 > len) break;
else {
l = r;
r = r + 1;
if (l == n) ok = true;
}
}
if (ok) break;
}
if (ok) {
cout << len << endl;
return ;
}
}
cout << n << endl;
}
D
根据完全二叉树最后一层有\(n\)个节点,则总共的节点数量为\(n*2-1\)个,建出完全二叉树。(虚空建图了,其实根本不需要写建树过程)
接下来从叶子结点向上遍历,记录左右子树的最大值和最小值,如果左子树的最大值大于右子树的最大值,则需要一次交换,且需要满足\(minval_{左子树}=maxval_{右子树}+1\)。
也可以用线段树做,这里完全二叉树也可以看做是一颗线段树,做的过程就是用左右子树的信息更新父亲结点的信息,和线段树\(build\)类似。
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
void solve() {
int n, m; cin >> n; m = n * 2 - 1;
vector<int> a(n + 1);
for (int i = 1;i <= n;i++) cin >> a[i];
if (n == 1) {
cout << 0 << endl;
return;
}
bool ok = true;
vector<int> g[m + 1], mx(m + 1), mi(m + 1), ans(m + 1);
for (int i = m;i > 1;i--) {
int p = i / 2;
g[p].push_back(i);
} //发现后面没有用到
function<void(int x)> dfs = [&](int x) {
int l = x * 2, r = x * 2 + 1;
if (r <= m) {
dfs(l); dfs(r);
ans[x] = ans[l] + ans[r];
mx[x] = max(mx[l], mx[r]);
mi[x] = min(mi[l], mi[r]);
if (mx[l] > mx[r] && mx[r] + 1 != mi[l]) ok = false;
if (mi[r] < mi[l] && mx[r] + 1 != mi[l]) ok = false;
if (mx[l] < mx[r] && mx[l] + 1 != mi[r]) ok = false;
if (mi[l] == mx[r] + 1) ans[x] ++;
}
else mx[x] = mi[x] = a[x - n + 1];
};
dfs(1);
if (!ok) cout << "-1\n";
else cout << ans[1] << endl;
}
signed main(void) {
cin.tie(nullptr), cout.tie(nullptr) -> ios::sync_with_stdio(false);
int t = 1;
cin >> t;
while (t --) solve();
return 0;
}
E
不够分奴,想过是\(dp\),但是没仔细想怎么转移。
记\(dp_i = true/false\)表示前i个数是否满足条件。
对所有的\(1\leq i\leq n\)有转移方程:
\(i - a_i - 1 >= 0,dp_i |= dp_{i - a_i - 1}\)
\(i + a_i <= n,dp_{i + a_i} |= dp_{i - 1}\)
int dp[200010];
void solve() {
int n; cin >> n;
vector<int> a(n + 1), pre[n + 1];
memset(dp, 0, sizeof dp);
for (int i = 1;i <= n;i++) cin >> a[i];
dp[0] = 1;
for (int i = 1;i <= n;i++) {
if (i - a[i] - 1 >= 0) dp[i] |= dp[i - a[i] - 1];
if (i + a[i] <= n) dp[i + a[i]] |= dp[i - 1];
}
cout << (dp[n] == 1 ? "YES\n" : "NO\n");
}
F
待补
G
待补

浙公网安备 33010602011771号