AtCoder Beginner Contest 245题解
赛时做到F
A - Good morning
题目描述:给你两个同一天内的24
时的时间,判断那一个时间更早。
思路:根据题意模拟即可。
时间复杂度:\(O(1)\)
参考代码:
void solve() {
int a, b, c, d;
cin >> a >> b >> c >> d;
string res = "Takahashi";
if (c < a || (c == a && d < b)) res = "Aoki";
cout << res << '\n';
return;
}
B - Mex
题目描述:给你一个数组,找出其中的MEX
。
思路:根据题意模拟即可
时间复杂度:\(O(n)\)
参考代码:
void solve() {
vector<int>cnt(2005, 0);
int n, a;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a;
cnt[a]++;
}
int res = 0;
while (cnt[res] != 0) ++res;
cout << res << '\n';
return;
}
C - Choose Elements
题目描述:给你两个长度为n
的数组A , B
和一个正整数 K
,你每次可以从A_i
,B_i
中选一个,然后按照顺序组成新数组C
,问这样组成的新数组是否满足\(|C_i - C_{i + 1}| \leq K , \forall 1 \leq i < n\)。
思路:比较明显,C
的第一个只能是\(A_1\)或者\(B_1\),那么我们分别以他们开始进行检验,每次可以根据当前值将下一个数的值的范围确定下来,若下一个数满足范围就可以设定新的范围,然后模拟即可。
时间复杂度:\(O(n)\)
参考代码:
void solve() {
int n, k;
cin >> n >> k;
vector<int>a(n + 1, 0), b(n + 1, 0);
for (int i = 1; i <= n; ++i) cin >> a[i];
for (int i = 1; i <= n; ++i) cin >> b[i];
auto check = [&](int lr, int rs) {
int lastlr = lr, lastrs = rs;
for (int i = 1; i <= n; ++i) {
if (a[i] >= lastlr && a[i] <= lastrs) {
if (b[i] < lastlr || b[i] > lastrs) lr = a[i] - k, rs = a[i] + k;
else lr = min(a[i] - k, b[i] - k), rs = max(a[i] + k, b[i] + k);
}
else if (b[i] >= lastlr && b[i] <= lastrs) lr = b[i] - k, rs = b[i] + k;
else return false;
lastlr = lr;
lastrs = rs;
}
return true;
};
if (check(a[1], a[1]) || check(b[1], b[1])) cout << "Yes" << '\n';
else cout << "No" << '\n';
return;
}
D - Polynomial division
题目描述:存在两个长度分别为\(n + 1\)和\(m + 1\)的多项式\(A,B\),他们的乘积为\(C\),现在已知\(A , C\),求\(B\)。
思路:考虑到这题数据量很小,不需要使用加速优化,直接按照除法模拟即可。
时间复杂度:\(O(nm)\)
参考代码:
void solve() {
int n, m;
cin >> n >> m;
vector<int>a(n + 1, 0),b(m + 1, 0), c(n + m + 1, 0);
for (int i = 0; i <= n; ++i) cin >> a[i];
for (int i = 0; i <= n + m; ++i) cin >> c[i];
int len = n + m;
for (int j = m; j >= 0; --j) {
if (c[len] == 0) b[j] = 0;
else b[j] = c[len] / a[n];
for (int i = 0; i <= n; ++i) c[i + j] -= b[j] * a[i];
--len;
}
for (auto&& num : b) cout << num << " ";
return;
}
E - Wrapping Chocolate
题目描述:有\(n\)个长方形的巧克力,第\(i\)个巧克力的长宽分别是\(A_i\)和\(B_i\),有\(m (n \leq m)\)个长方形盒子,第\(i\)个盒子的长宽分别为\(C_i\)和\(D_i\)。当第\(j\)个盒子可以装下第\(i\)个巧克力时,必须满足条件\(A_i \leq C_j\)且\(B_i \leq D_j\)。问是否可以将所有巧克力都装入盒子中。
思路:假定长宽分别用\(x\)和\(y\)表示,那么我们按照\(y\)排序之后,倒序枚举贪心,对于当前枚举的巧克力,找最小的\(x\)满足\(x\)大于等于其长度即可。这个\(x\)可以用一个multiset
维护。
时间复杂度:\(O(nlogn)\)
参考代码:
struct Node {
int u, v;
Node(int _u = 0 , int _v = 0):u(_u) , v(_v){}
};
void solve() {
int n, m;
cin >> n >> m;
vector<Node>a(n + 1), b(m + 1);
for (int i = 1; i <= n; ++i) cin >> a[i].u;
for (int i = 1; i <= n; ++i) cin >> a[i].v;
for (int i = 1; i <= m; ++i) cin >> b[i].u;
for (int i = 1; i <= m; ++i) cin >> b[i].v;
sort(a.begin(), a.end(), [&](const Node& a, const Node& b) {
return a.v < b.v;
});
sort(b.begin(), b.end(), [&](const Node& a, const Node& b) {
return a.v < b.v;
});
multiset<int> st;
int idx = m;
for (int i = n; i >= 1; --i) {
while (idx > 0 && b[idx].v >= a[i].v) st.insert(b[idx].u), --idx;
if (st.empty()) {
cout << "No" << '\n';
return;
}
auto iter = st.lower_bound(a[i].u);
if (iter == st.end()) {
cout << "No" << '\n';
return;
}
st.erase(iter);
}
cout << "Yes" << '\n';
return;
}
F - Endless Walk
题目描述:给你\(n\)个点\(m\)条边的有向图,问你有多少个顶点满足:从该点出发,可以无限走下去。
思路:明显有环的时候就可以无限走下去,若一个点可以到达这个环,说明它也可以无限走下去。所以我们可以使用tarjan
算法缩点之后建反图,从连通分量大于1
的新结点出发做BFS
,最终统计点的数量即可。这个做法比较垃圾,被某位神嘲讽了QAQ。
时间复杂度:\(O(n + m)\)
参考代码:
void solve() {
int n, m;
cin >> n >> m;
vector<vector<int>>graph(n + 1);
for (int i = 1; i <= m; ++i) {
int u, v;
cin >> u >> v;
graph[u].push_back(v);
}
vector<int>dfn(n + 1, 0), low(n + 1, 0);
int dfncnt = 0;
vector<int>s(n + 1, 0), inStack(n + 1, 0);
int top = 0;
vector<int>scc(n + 1, 0), sz(n + 1, 0);
int sc = 0;
auto tarjan = [&](auto&& tarjan, int u)->void {
low[u] = dfn[u] = ++dfncnt;
s[++top] = u;
inStack[u] = 1;
for (auto& v : graph[u]) {
if (!dfn[v]) {
tarjan(tarjan, v);
low[u] = min(low[u], low[v]);
}
else if (inStack[v]) low[u] = min(low[u], dfn[v]);
}
if (dfn[u] != low[u]) return;
++sc;
while (s[top] != u) {
scc[s[top]] = sc;
sz[sc]++;
inStack[s[top--]] = 0;
}
scc[s[top]] = sc;
sz[sc]++;
inStack[s[top--]] = 0;
return;
};
for (int i = 1; i <= n; ++i) {
if (dfn[i]) continue;
tarjan(tarjan, i);
}
map<int, int>mp;
for (int i = 1; i <= n; ++i) mp[scc[i]]++;
vector<vector<int>>ngraph(sc + 1);
for (int i = 1; i <= n; ++i) {
for (auto&& v : graph[i]) {
ngraph[scc[v]].push_back(scc[i]);
}
}
queue<int>q;
vector<bool>vis(sc + 1, 0);
for (int i = 1; i <= sc; ++i) {
if (mp[i] > 1) q.push(i), vis[i] = true;
}
while (!q.empty()) {
auto u = q.front(); q.pop();
for (auto& v : ngraph[u]) {
if (vis[v]) continue;
vis[v] = true;
q.push(v);
}
}
int res = 0;
for (int i = 1; i <= sc; ++i)if (vis[i]) res += mp[i];
cout << res << '\n';
return;
}
作者:cherish.
出处:https://home.cnblogs.com/u/cherish-/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。