A. Thermometer
模拟
代码实现
#include <bits/stdc++.h>
using namespace std;
int main() {
double x;
cin >> x;
if (x >= 38) puts("1");
else if (x >= 37.5) puts("2");
else puts("3");
return 0;
}
B. Ticket Gate Log
模拟
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
string s;
cin >> s;
int ans = 0;
char expect = 'i';
for (char c : s) {
if (c != expect) ans++;
expect = c^'o'^'i';
}
if (s.back() == 'i') ans++;
cout << ans << '\n';
return 0;
}
C. Variety Split Easy
前后缀分解
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n;
cin >> n;
vector<int> a(n);
rep(i, n) cin >> a[i];
vector<int> numl(n+1), numr(n+1);
{
unordered_set<int> st;
rep(i, n) {
st.insert(a[i]);
numl[i+1] = st.size();
}
}
{
unordered_set<int> st;
for (int i = n-1; i >= 0; --i) {
st.insert(a[i]);
numr[i] = st.size();
}
}
int ans = 0;
for (int i = 1; i < n; ++i) {
ans = max(ans, numl[i]+numr[i]);
}
cout << ans << '\n';
return 0;
}
D. Cubes
\(N = x^3 - y^3 = (x-y)(x^2+ xy + y^2)\)
记 \(d = x-y\)
我们可以枚举这个 \(d\)
\(x = y+d\)
\(x^3 - y^3 = d^3 + 3yd(y+d)\)
\(d^3 < N\)
\(y(y+d) = \frac{N-d^3}{3d}\)
其中 \(\frac{N-d^3}{3d}\) 是个常数,不妨记为 \(C\)
\(y^2 + dy - C = 0\)
然后用求根公式解出 \(y\)
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
int main() {
ll n;
cin >> n;
for (ll d = 1; d*d*d < n; ++d) {
ll c = n-d*d*d;
if (c%(3*d)) continue;
c /= 3*d;
ll y = (sqrt(d*d+4*c)-d)/2;
if (y*y+d*y-c == 0) {
cout << y+d << ' ' << y << '\n';
return 0;
}
}
cout << "-1\n";
return 0;
}
E. Path Decomposition of a Tree
任选一个点作为根,并考虑包含叶子的路径会发生什么,就会发现最终只能依次割掉大小为 \(K\) 的子树。可以用 \(\operatorname{dfs}\) 来实现
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n, k;
cin >> n >> k;
int nk = n*k;
vector<vector<int>> to(nk);
rep(i, nk-1) {
int a, b;
cin >> a >> b;
--a; --b;
to[a].push_back(b);
to[b].push_back(a);
}
bool ok = true;
auto dfs = [&](auto& f, int v, int p=-1) -> int {
int res = 1;
int deg = 0;
for (int u : to[v]) {
if (u == p) continue;
int sz = f(f, u, v);
if (sz%k) deg++;
res += sz;
}
if (res%k) deg++;
if (deg > 2) ok = false;
return res;
};
dfs(dfs, 0);
if (ok) puts("Yes");
else puts("No");
return 0;
}
F. Variety Split Hard
记 dp[j][i] 表示将前 \(i\) 个数分成 \(j\) 段时的最大值
\( dp[j+1][i] = \max\limits_{p < i} (dp[j][p] + f(p, i)) \)
其中 \(f(p, i)\) 表示 \((A_{p+1},A_{p+2}, \cdots, A_i)\) 的种类数
然后用线段树来加速即可
同时这种做法和加强版 CF833B 一样
代码实现
#include <bits/stdc++.h>
#include <atcoder/all>
using namespace atcoder;
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int op(int x, int y) { return max(x, y); }
int e() { return 0; }
int mapping(int f, int x) { return x+f; }
int composition(int f, int g) { return f+g; }
int id() { return 0; }
int main() {
int n;
cin >> n;
vector<int> a(n);
rep(i, n) cin >> a[i];
vector<int> pre(n);
{
vector<int> pos(n+1, -1);
rep(i, n) {
pre[i] = pos[a[i]];
pos[a[i]] = i;
}
}
using seg = lazy_segtree<int, op, e, int, mapping, composition, id>;
vector<seg> t(3, seg(n));
rep(i, n) {
rep(j, 2) {
int now = t[j].all_prod();
t[j+1].set(i, now);
}
rep(j, 3) {
t[j].apply(pre[i]+1, i+1, 1);
}
}
int ans = t[2].all_prod();
cout << ans << '\n';
return 0;
}
G. Maximize Distance
首先,考虑“是否可以将最短距离增加到 1 以上?”时,问题就变成了“删除若干条边,使得无法从点 \(1\) 到达点 \(N\)”,因此是最小割问题!如果用同样的思路来思考原问题,就会发现它也是一个"\(k\) 值燃烧填充"问题,可以通过最小割来解决!
浙公网安备 33010602011771号