A. delete .
正则表达式
代码实现
#include <bits/stdc++.h>
using namespace std;
int main() {
string s;
cin >> s;
string ans = regex_replace(s, regex(R"(\.)"), "");
cout << ans << '\n';
return 0;
}
B. 3^A
从高位到低位进行贪心
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int m;
cin >> m;
vector<int> a;
for (int i = 10; i >= 0; --i) {
int x = 1;
rep(j, i) x *= 3;
while (m >= x) {
m -= x;
a.push_back(i);
}
}
cout << a.size() << '\n';
for (int x : a) cout << x << ' ';
return 0;
}
C. Count ABC Again
只需处理字符修改前后对答案的影响即可
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n, q;
cin >> n >> q;
string s;
cin >> s;
int ans = 0;
auto add = [&](int i, int co=1) {
if (i < 0) return;
if (s.substr(i, 3) == "ABC") ans += co;
};
auto add3 = [&](int i, int co=1) {
add(i-2, co);
add(i-1, co);
add(i, co);
};
rep(i, n-2) add(i);
rep(qi, q) {
int x; char c;
cin >> x >> c;
--x;
// delate
add3(x, -1);
s[x] = c;
// add
add3(x);
cout << ans << '\n';
}
return 0;
}
D. Buildings
可以从后开始考虑,维护一个单调递减的栈
代码实现
#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> h(n);
rep(i, n) cin >> h[i];
vector<int> ans(n);
vector<int> st;
for (int i = n-1; i >= 0; --i) {
ans[i] = st.size();
while (st.size() and st.back() < h[i]) st.pop_back();
st.push_back(h[i]);
}
rep(i, n) cout << ans[i] << ' ';
return 0;
}
E. K-th Largest Connected Components
可以用并查集来维护每个连通块中前 \(10\) 大的点
代码实现
#include <bits/stdc++.h>
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
#endif
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n, q;
cin >> n >> q;
dsu uf(n);
vector<vector<int>> top(n);
rep(i, n) top[i].push_back(i);
rep(qi, q) {
int type;
cin >> type;
if (type == 1) {
int u, v;
cin >> u >> v;
--u; --v;
u = uf.leader(u);
v = uf.leader(v);
if (u == v) continue;
vector<int> d = top[u];
d.insert(d.end(), top[v].begin(), top[v].end());
ranges::sort(d, greater<>());
if (d.size() > 10) d.resize(10);
uf.merge(u, v);
top[uf.leader(u)] = d;
}
else {
int v, k;
cin >> v >> k;
--v;
v = uf.leader(v);
int ans = -1;
if (top[v].size() >= k) ans = top[v][k-1]+1;
cout << ans << '\n';
}
}
return 0;
}
F. Teleporting Takahashi 2
记 dp[i][v]
表示走 \(i\) 步移动到点 \(v\) 的路径数
这样状态数就有 \(\mathcal{O}(NK)\) 了,显然不行
记图上额外边的两端点称为特殊点
注意到环上相邻两点之间的特殊点只有一种走法,所以会比较浪费,可以一次性花这两点之间的边数的代价走到另一个点上
可以发现最多有 \(O(M)\) 个特殊点
对于转移,可以由 \(dp[i]\) 转移到 \(dp[i+1]\) 会比较方便,这样就可以在不考虑第一维的情况下将状态数变成了 \(\mathcal{O}(N)\),可以参考官解图示的转移方式
代码实现
#include <bits/stdc++.h>
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
#endif
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using mint = modint998244353;
int main() {
int n, m, k;
cin >> n >> m >> k;
vector<int> x(m), y(m);
rep(i, m) {
cin >> x[i] >> y[i];
--x[i]; --y[i];
}
deque<mint> dp(n);
dp[0] = 1;
rep(ki, k) {
vector<mint> val(m);
rep(i, m) val[i] = dp[x[i]];
dp.push_front(dp.back());
dp.pop_back();
rep(i, m) dp[y[i]] += val[i];
}
mint ans;
rep(i, n) ans += dp[i];
cout << ans.val() << '\n';
return 0;
}
G. Ax + By < C
半平面交+类欧