AtCoder Beginner Contest 235 题解
作者:@cherish.
课程学习内容为作者从学校的PPT处摘抄,仅供自己学习参考,若需转载请注明出处:https://www.cnblogs.com/cherish-/p/15808200.html
赛时做到E,看到F觉得不会就直接开摆惹
A - Rotate
题目描述:给你一个三位数,不含数字,假设这三位数用表示,求
思路:根据题目描述模拟即可
时间复杂度:
参考代码:
void solve() {
string s;
cin >> s;
auto f = [&](int a, int b, int c) {
return a * 100 + b * 10 + c;
};
int res = f(s[0] - '0', s[1] - '0', s[2] - '0');
res += f(s[1] - '0', s[2] - '0', s[0] - '0');
res += f(s[2] - '0', s[0] - '0', s[1] - '0');
cout << res << '\n';
return;
}
B - Climbing Takahashi
题目描述:给你长度为的数组,求最大的使得,特别的。
数据范围:
思路:根据题意模拟即可
时间复杂度:
参考代码:
void solve() {
int n(0), h(0);
int res = 0;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> h;
if (h > res) res = h;
else break;
}
cout << res << '\n';
return;
}
C - The Kth Time Query
题目描述:给你一个长度为的数组,给你个询问,每次询问表示数字在中第次出现的位置。若大于的数量或者中不存在整数输出。
思路:考虑到比较大,使用unordered_map
映射一下再使用vector
存储一下下标即可。
时间复杂度:
参考代码:
unordered_map<int, vector<int>>mp;
void solve() {
int n(0), q(0), a;
cin >> n >> q;
for (int i = 1; i <= n; ++i) {
cin >> a;
mp[a].push_back(i);
}
int x(0), k(0);
while (q--) {
cin >> x >> k;
if (mp.count(x) == 0 || mp[x].size() < k) cout << "-1\n";
else cout << mp[x][k - 1] << '\n';
}
return;
}
D - Multiply and Rotate
题目描述:给你两个整数,初始时你有一个整数,每次你可以将当前数字乘以即,或者在满足时,将最低位的数字变成最高位,比如123
,进行该操作后变成312
。问将变为的最小操作次数,若无法实现,输出-1
。
数据范围:
思路:考虑BFS
进行求解即可,注意过程中可能超过int
的表示范围,所以需要开long long
或者特判一下。
时间复杂度:(因为得到的数字个数不超过)
参考代码:
struct Node {
long long val;
int step;
Node(long long _val = 0 , int _step = 0):val(_val) , step(_step){}
};
void solve() {
int a(0), n(0);
cin >> a >> n;
auto f = [](string s) {
int ans = 0, len = s.size();
ans = s.back() - '0';
for (int i = 0; i < len - 1; ++i) ans = ans * 10 + s[i] - '0';
return ans;
};
queue<Node> q;
q.push({ 1ll , 0 });
int res = -1, cnt = 0;
vector<bool>vis(1000005, false);
while (!q.empty()) {
auto [val, step] = q.front();
q.pop();
vis[val] = true;
long long dx = 1ll * val * a;
if (dx == n) {
res = step + 1;
break;
}
if (dx <= 1000000 && vis[dx] == false) {
vis[dx] = true;
q.push({ dx , step + 1 });
}
if (val >= 10 && val % 10 != 0) {
dx = f(to_string(val));
if (dx <= 1000000 && vis[dx] == false) {
if (dx == n) {
res = step + 1;
break;
}
q.push({ dx , step + 1 });
vis[dx] = true;
}
}
}
cout << res << '\n';
return;
}
E - MST + 1
题目描述:给你一个带权无向图,可能存在重边和自环,该图的边权两两不同。给你个询问,每次询问给你一条边,问若将加入图中,新图的最小生成树是否含有边,若含有输出Yes
,否则输出No
。注意的边权与原图中的边权也不同。
思路:我们先求出原图的最小生成树,那么对于每次询问就是若加上该条边,就构成了一个环,而要变成树,需要删除其中的一条边,考虑到是最小生成树,所以删除的是权最大的边。所以我们先将原图的最小生成树求出来,然后对于每次询问,我们求上路径的最大边权,若最大边权大于则输出Yes
,否则输出No
。对于求路径最大边权,我使用了树链剖分,码量有点大,可以选用其他方法如:倍增。
时间复杂度:
参考代码:
const int N = 2e5 + 5;
struct Edge {
int u, v, w;
Edge(int _u = 0, int _v = 0, int _w = 0):u(_u) , v(_v) , w(_w){}
bool operator < (const Edge& a)const {
return w < a.w;
}
};
struct Node {
int v, w;
Node(int _v , int _w):v(_v) , w(_w){}
};
vector<vector<Node>>graph(N);
int a[N];
int fa[N], dep[N], siz[N], son[N];
void dfs1(int u, int f) {
fa[u] = f; dep[u] = dep[f] + 1;
siz[u] = 1;
int maxsize = -1;
for (auto g : graph[u]) {
if (g.v == f) continue;
a[g.v] = g.w;
dfs1(g.v, u);
siz[u] += siz[g.v];
if (siz[g.v] > maxsize) maxsize = siz[g.v], son[u] = g.v;
}
return;
}
int tim, dfn[N], top[N], weight[N];
void dfs2(int u, int t) {
dfn[u] = ++tim;
top[u] = t;
weight[tim] = a[u];
if (!son[u]) return;
dfs2(son[u], t);
for (auto g : graph[u]) {
if (g.v == fa[u] || g.v == son[u]) continue;
dfs2(g.v, g.v);
}
return;
}
struct SegmentTree {
int max, lr, rs, mid;
};
SegmentTree tree[N << 2];
void pushUp(int rt) {
tree[rt].max = max(tree[rt << 1].max, tree[rt << 1 | 1].max);
return;
}
void buildTree(int rt, int lr, int rs) {
tree[rt].max = 0;
tree[rt].lr = lr; tree[rt].rs = rs;
if (lr == rs) {
tree[rt].max = weight[lr];
return;
}
int mid = tree[rt].mid = lr + rs >> 1;
buildTree(rt << 1, lr, mid);
buildTree(rt << 1 | 1, mid + 1, rs);
pushUp(rt);
return;
}
int query(int rt, int lr, int rs) {
if (lr > tree[rt].rs || tree[rt].rs < lr) return 0;
if (tree[rt].lr >= lr && tree[rt].rs <= rs) return tree[rt].max;
int res = 0;
if (tree[rt].mid >= lr) res = max(res, query(rt << 1, lr, rs));
if (tree[rt].mid < rs) res = max(res, query(rt << 1 | 1, lr, rs));
return res;
}
int queryChain(int u, int v) {
int res = 0;
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) std::swap(u, v);
res = max(res, query(1, dfn[top[u]], dfn[u]));
u = fa[top[u]];
}
if (dep[u] > dep[v]) std::swap(u, v);
res = max(res, query(1, dfn[u] + 1, dfn[v]));
return res;
}
void solve() {
vector<Edge>edges;
int n, m, u, v, w, q;
cin >> n >> m >> q;
for (int i = 1; i <= m; ++i) {
cin >> u >> v >> w;
edges.push_back({ u , v , w });
edges.push_back({ v , u , w });
}
vector<int>parent(n + 1, 0);
for (int i = 1; i <= n; ++i) parent[i] = i;
auto find = [&](auto find, int u)-> int{
if (parent[u] != u) parent[u] = find(find , parent[u]);
return parent[u];
};
sort(edges.begin(), edges.end());
for (auto [u, v, w] : edges) {
u = find(find, u); v = find(find, v);
if (u == v) continue;
graph[u].push_back({ v , w });
graph[v].push_back({ u , w });
parent[u] = v;
}
dfs1(1, 1);
dfs2(1, 1);
buildTree(1, 1, n);
while (q--) {
cin >> u >> v >> w;
int res = queryChain(u, v);
if (res < w) cout << "No" << '\n';
else cout << "Yes" << '\n';
}
return;
}
作者:cherish.
出处:https://home.cnblogs.com/u/cherish-/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!