ABC338

0|1基本情况

A忘记大小写敏感卡了20分钟,BC秒了,E用树状数组草过去了,D错了25个点,似乎是交界没有判断好。

1|0B - Frequency

B - Frequency (atcoder.jp)

这题还可以更优雅点。

int main() { string s; cin >> s; map<char, int> cnt; for (int i = 0; i < s.size(); i++) { cnt[s[i]]++; } vector<pair<char,int> > a(cnt.begin(), cnt.end()); sort(a.begin(), a.end(), [&](auto& x, auto& y) { if (x.second == y.second) return x.first < y.first; return x.second > y.second; }); cout << a.front().first << endl; return 0; }

赛时急着过题,写的很无脑,复杂度有 O(n×logn)

其实这类字母题完全可以照着字母枚举,复杂度直接降低到 O(n)

int main() { string s; cin >> s; int cnt[26] = {0}; const char d = 'a'; for (char c : s) ++cnt[c - d]; int ans = 0; for (int i = 0; i < 26; i++) if (cnt[i] > cnt[ans]) { ans = i; } cout << (char)(ans + d) << endl; }

2|0D - Island Tour

D - Island Tour (atcoder.jp)

我的想法是贪心选取每一对相邻点的最短路,然后最后判断断点是否会影响答案,会的话贪心的替换最优的另一条路。

int main() { int n, m; cin >> n >> m; vector<ll> a(m); ll ans = 0; for (ll& x : a) cin >> x; vector<pair<ll, ll> > res; ll f1_l = inf, f1_r = -1, f2_l = inf, f2_r = -1; bool f1 = false, f2 = false; vector<int> cnt1_l(n + 1), cnt1_r(n + 1), cnt2_l(n + 1), cnt2_r(n + 1); for (int i = 1; i < m; i++) { ll x = max(a[i], a[i - 1]), y = min(a[i], a[i - 1]); if (x - y < n - x + y) { res.emplace_back(make_pair(x - y, n - x + y)); f1_l = min(f1_l, y); cnt1_l[f1_l]++; f1_r = max(f1_r, x); cnt1_r[f1_r]++; f1 = true; } else { res.emplace_back(make_pair(n - x + y, x - y)); f2_l = min(f2_l, y); cnt2_l[f2_l]++; f2_r = max(f2_r, x); cnt2_r[f2_r]++; f2 = true; } ans += min(x - y, n - x + y); } if (f1 && f2 && f2_l >= f1_l && f2_r <= f1_r) { sort(res.begin(), res.end(), [&](auto& x1, auto& x2) { return (x1.second - x1.first) < (x2.second - x2.first); }); ans -= res.front().first; ans += res.front().second; } else if (f1 && !f2 && cnt1_l[f1_l] > 1 || cnt1_r[f1_r] > 1) { sort(res.begin(), res.end(), [&](auto& x1, auto& x2) { return (x1.second - x1.first) < (x2.second - x2.first); }); ans -= res.front().first; ans += res.front().second; } else if (!f1 && f2 && cnt2_l[f2_l] > 1 || cnt2_r[f2_r] > 1) { sort(res.begin(), res.end(), [&](auto& x1, auto& x2) { return (x1.second - x1.first) < (x2.second - x2.first); }); ans -= res.front().first; ans += res.front().second; } cout << ans << endl; return 0; }

但是这个方法根本就不对,无法确保当一条路被断掉时,只有一条路径会被影响

正解就是暴力枚举每一条边断的情况,然后利用差分思想优化。

但我只会差分模板,思想并不深刻,待我复习。

复习回来啦。

  • 枚举每一条边断开,利用差分数组 vi 表示第 i 边断开时总的代价。
  • 对于每一对 ai,ai+1,无非两种走法,要么顺时针,要么逆时针。
    • 如果顺时针走法中的路径断了,那就只能逆时针
      • 那么就对顺时针区间维护上逆时针走法的代价
    • 如果逆时针走法中的路径断了,那就只能顺时针
      • 那么就对逆时针区间维护上逆时针走法的代价
  • 最后差分倒退回来原数组,求最小的 vi
int main() { int n, m; cin >> n >> m; vector<int> a(m); for (int& x : a) cin >> x, x--; vector<ll> v(n + 1); auto dist = [&](int from, int to) {//计算贡献 if (from <= to) return to - from; else return to + n - from; }; auto add = [&](int from, int to, int num) {//维护差分 if (from <= to) { v[from] += num; v[to] -= num; } else { v[from] += num; v[n] -= num; v[0] += num; v[to] -= num; } }; for (int i = 0; i + 1 < m; i++) {//A、B路径为顺逆时针 add(a[i], a[i + 1], dist(a[i + 1], a[i]));//如果A路径走不了,把走B路径的代价维护上去 add(a[i + 1], a[i], dist(a[i], a[i + 1]));//如果B路径走不了,把走A路径的代价维护上去 } ll ans = 1LL << 60; for (int i = 0; i < n; i++) { v[i + 1] += v[i];//差分还原原数组 ans = min(ans, v[i]); } cout << ans << endl; return 0; }

3|0E - Chords

E - Chords (atcoder.jp)

先破环为链,题目就转变成一个区间内有没有线段相交。

所以做法就是按左端点排序,判断所有区间是不是有完全被包含进去或者完全没有关系。

signed main() { std::cin.tie(nullptr)->sync_with_stdio(false); int n; std::cin >> n; std::vector<std::pair<int, int>> seg(n); for (auto&[l, r] : seg) {std::cin >> l >> r; if (l > r) {std::swap(l, r);}} std::sort(all(seg)); std::vector<std::pair<int, int>> stk; bool ok = false; for (auto&[l, r] : seg) { while (not stk.empty() and l > stk.back().second) {stk.pop_back();}//左端点比栈顶右端点还大,说明两个区间完全没有关系 if (not stk.empty() and r > stk.back().second) {ok = true;}//说明当前l<=栈顶r,并且当前r又大于栈顶r,那么就是有相交,即没有被完全包含进去 stk.emplace_back(l, r); } std::cout << (ok ? "Yes\n" : "No\n"); return 0; }

__EOF__

本文作者Kdlyh
本文链接https://www.cnblogs.com/kdlyh/p/17992699.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   加固文明幻景  阅读(111)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示