ABC341
D - Only one of two
https://atcoder.jp/contests/abc341/tasks/abc341_d
数论,二分求第K大
设
那么,有
此外,计数是随着
因此,可以利用这一性质通过二分搜索来解决这个问题。在此问题的约束条件下,答案总是最多为
更具体地说,我们可以设置
- 让
. - 如果是
,则设为 ;否则,设为 。
答案就是结果
对于固定的
signed main() {
std::cin.tie(nullptr)->sync_with_stdio(false);
i64 n, m, k;
std::cin >> n >> m >> k;
i64 lo = 0, hi = 2E18;
i64 L = std::lcm(n, m);
while (lo <= hi) {
i64 mid = lo + hi >> 1;
if ((mid / n) + (mid / m) - 2 * (mid / L) < k) {
lo = mid + 1;
} else {
hi = mid - 1;
}
}
std::cout << hi + 1 << '\n';
return 0;
}
E - Alternating String
https://atcoder.jp/contests/abc341/tasks/abc341_e
转化题意再用线段树维护
考虑线段树要维护什么信息
对于长度为
-
那么,第一类型的查询
1 L R
会将 修改为 和 。
在这里,如果 或 ,则前者或后者的更新是不必要的。 -
另一方面,第二类型的查询
2 L R
若 ,则输出Yes
,否则输出No
。注意到每个
取值为 或 ,可以通过判断 来决定输出是否为Yes
。
这些操作可以通过线段树实现。
每种查询都可以在
在实现上述算法时,需要注意当
signed main() {
std::cin.tie(nullptr)->sync_with_stdio(false);
int n, m;
std::cin >> n >> m;
std::string s;
std::cin >> s;
SegmentTree<Info> T(n);
for (int i = 0; i + 1 < n; i++) {
if (s[i] != s[i + 1]) {T.modify(i, 1);}
else {T.modify(i, 0);}
}
for (int i = 0, x, l, r; i < m; i++) {
std::cin >> x >> l >> r; --l;
if (x == 1) {
if (l > 0) {T.modify(l - 1, 1 - T.rangeQuery(l - 1, l).sum);}
if (r < n) {T.modify(r - 1, 1 - T.rangeQuery(r - 1, r).sum);}//注意这里是r - 1,因为r是开区间
} else {
std::cout << (T.rangeQuery(l, r - 1).sum == r - l - 1 ? "Yes" : "No") << '\n';
}
}
return 0;
}
F - Breakdown
设
如果您从顶点
这里,
由于
对于固定的
对于与
相邻的每个顶点 , 的 价值 为 ,其 成本 为 。在总成本为 的约束下,最大化所选顶点的总价值。
这可以通过 DP 在
由于
其中
signed main() {
int N, M;
std::cin >> N >> M;
std::vector adj(N, std::vector<int>());
for (int i = 0, u, v; i < M; i++) {
std::cin >> u >> v; --u; --v;
adj[u].push_back(v); adj[v].push_back(u);
}
std::vector<int> W(N), A(N);
for (auto& x : W) {std::cin >> x;}
for (auto& x : A) {std::cin >> x;}
std::vector<int> p(N);//维护点权对应的下标
std::iota(all(p), 0);
std::sort(all(p), [&](int i, int j){return W[i] < W[j];});
std::vector<int> dp(N);
for (auto& x : p) {//按照W[i]升序更新
std::vector<int> f(W[x]);//找到当前容积下能放入的最大点数
for (auto& y : adj[x]) if (W[y] < W[x]) {
for (int i = W[x] - 1; i >= W[y]; i--) {
f[i] = std::max(f[i], f[i - W[y]] + dp[y]);
}
}
dp[x] = 1 + f[W[x] - 1];
}
i64 ans = 0;
for (int i = 0; i < N; i++) {ans += 1LL * A[i] * dp[i];}
std::cout << ans << '\n';
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!