Educational Codeforces Round 4 覆盤
阿新 • • 發佈:2021-10-19
A
讀完題總是會楞一下,然後才開始寫。
一遍 AC。
const int MAXN = 100 + 10; int n, p, q; char ss[MAXN]; int main() { scanf("%d %d %d", &n, &p, &q); scanf("%s", ss); for (int ps = 0; ps <= n; ++ps) { if ((n - ps * p) < 0) break; if ((n - ps * p) % q) continue; int qs = (n - ps * p) / q; printf("%d", ps + qs); for (int i = 0; i < ps * p; ++i) { if (i % p == 0) puts(""); putchar(ss[i]); } for (int i = ps * p; i < n; ++i) { if ((i - ps * p) % q == 0) puts(""); putchar(ss[i]); } return 0; } puts("-1"); return 0; }
B
讀題就讀了好幾分鐘。讀懂了就很好寫了。
一遍 AC。
const int MAXN = 2e5 + 10;
int pos[MAXN];
int n;
int main() {
n = read();
rep (i, 1, n) pos[read()] = i;
lli ans = 0;
rep (i, 1, n - 1) ans += std::abs(pos[i] - pos[i + 1]);
printf("%lld\n", ans);
return 0;
}
C
第一發忘了判斷棧是否為空,然後 WA on 10
const int MAXN = 1e6 + 10; int n; char ss[MAXN]; std::stack<char> stk; int main() { scanf("%s", ss + 1); int ans = 0; n = (int) strlen(ss + 1); rep (i, 1, n) { if (ss[i] == '<' || ss[i] == '{' || ss[i] == '[' || ss[i] == '(') { stk.push(ss[i]); } else { if (stk.empty()) { puts("Impossible"); return 0; } switch (ss[i]) { case '>': ans += (stk.top() != '<'); break; case '}': ans += (stk.top() != '{'); break; case ']': ans += (stk.top() != '['); break; case ')': ans += (stk.top() != '('); break; } stk.pop(); } } if (stk.empty()) printf("%d\n", ans); else puts("Impossible"); return 0; }
D. The Union of k-Segments
類似於之前 ABC 某題的思路,先離散化,然後差分,統計答案的時候用原陣列的值。
但是這麼做只能處理整數端點,對於 \([1, 2] + [3, 4]\) 這種是沒法處理的,所以考慮把端點都 \(\times 2\),然後在離散化數組裡加入 \(2l - 1, 2l, 2r, 2r + 1\) 四個值,這樣就能很方便處理了。
然後調了一場沒調出來,賽後才發現自己訪問原陣列的時候腦抽了,std::vector
從 0 開始儲存結果少減了一個 1.
#易錯警示:分清 0-indexed 和 1-indexed 的區別。
const int MAXN = 1e6 + 10; int n, k; int tl[MAXN], tr[MAXN]; std::vector<int> lisan; int diff[MAXN << 2]; int main() { n = read(); k = read(); rep (i, 1, n) { int u = read(); int v = read(); tl[i] = u, tr[i] = v; lisan.push_back(u * 2 - 1); lisan.push_back(u * 2); lisan.push_back(v * 2); lisan.push_back(v * 2 + 1); } std::sort(ALL(lisan)); auto it = std::unique(ALL(lisan)); if (it != lisan.end()) lisan.erase(it, lisan.end()); rep (i, 1, n) { int fl = (int) (std::lower_bound(ALL(lisan), tl[i] * 2) - lisan.begin() + 1); int fr = (int) (std::lower_bound(ALL(lisan), tr[i] * 2) - lisan.begin() + 1); // DEBUG(fl); DEBUG(fr); ++diff[fl]; --diff[fr + 1]; } rep (i, 1, (int) lisan.size() + 1) diff[i] += diff[i - 1]; // rep (i, 1, (int) lisan.size() + 1) printf("%d ", diff[i]); int tl = 0; std::vector<std::pair<int, int> > anss; lisan.push_back(0); rep (i, 1, (int) lisan.size() - 1) { if (diff[i] < k) { if (tl) { anss.push_back({lisan[tl - 1] / 2, (lisan[i - 2]) / 2}); tl = 0; } } else { if (!tl) tl = i; } } printf("%d\n", (int) anss.size()); for (auto v : anss) { printf("%d %d\n", v.fi, v.se); } return 0; }
或者有更簡單的做法,你甚至不需要一個完整的 diff
陣列,只需要把左端點看成一個 +1 的事件,右端點看成一個 -1 的事件,然後排個序按上面的過程掃一遍就可以了。
const int MAXN = 1e6 + 10;
int n, k;
struct Seg { int l, x; }; std::vector<Seg> events;
bool operator < (const Seg &x, const Seg &y) { return x.l == y.l ? x.x > y.x : x.l < y.l; }
int main() {
n = read(); k = read();
rep (i, 1, n) {
int l = read(); int r = read();
events.push_back({l * 2 - 1, 0});
events.push_back({l * 2, 1});
events.push_back({r * 2 + 1, -1});
} std::sort(ALL(events));
std::vector<std::pair<int, int> > ans;
int cnt = 0;
int tl = -(1 << 30);
for (auto e : events) {
cnt += e.x;
if (cnt >= k) {
if (tl == -(1 << 30)) tl = e.l;
} else {
if (tl != -(1 << 30)) {
ans.push_back({tl, e.l - 1});
tl = -(1 << 30);
}
}
}
printf("%d\n", (int) ans.size());
for (auto v : ans) printf("%d %d\n", v.fi / 2, v.se / 2);
return 0;
}