Educational Codeforces Round 105 (Rated for Div. 2)
A - ABC String
第一個字母只能是 '(', 最后一個字母不等於第一個字母且只能是 ')'
所以就剩下一個字母沒確定, 直接分情況討論兩邊即可
int a[3], x[2], y[2];
int main() {
IOS;
for (cin >> _; _; --_) {
string s; cin >> s; bool f = 1, g = 1;
memset(a, -1, sizeof a); rep (i, 0, 1) x[i] = y[i] = 0;
if (s[0] == s.back()) { cout << "NO\n"; continue; }
a[s[0] - 'A'] = 0; a[s.back() - 'A'] = 1;
for (auto &i : s) {
if (a[i - 'A'] != -1) ++x[a[i - 'A']], ++y[a[i - 'A']];
else ++x[0], ++y[1];
if (x[0] < x[1]) f = 0;
if (y[0] < y[1]) g = 0;
}
if (f && x[0] == x[1]) cout << "YES\n";
else if (g && y[0] == y[1]) cout << "YES\n";
else cout << "NO\n";
}
return 0;
}
B - Berland Crossword
狀壓枚舉四個角有沒有黑塊
int a[5], b[5];
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n; rep (i, 1, 4) cin >> a[i]; bool f = 0;
rep (i, 0, (1 << 4) - 1) {
rep (i, 1, 4) b[i] = a[i];
if (i & 1) --b[1], --b[4];
if (i >> 1 & 1) --b[1], --b[2];
if (i >> 2 & 1) --b[2], --b[3];
if (i >> 3 & 1) --b[3], --b[4];
bool g = 1;
rep (i, 1, 4) if (b[i] < 0 || b[i] > n - 2) g = 0;
f = f || g;
}
cout << (f ? "YES\n" : "NO\n");
}
return 0;
}
C - 1D Sokoban
直接正負對稱, 直接把負數 reverse, 在取反, 就是兩次相同的過程
然后就是模擬推箱子取max即可
ll a[N], b[N];
int work(int x, int y, int n, int m) {
int ans = 0, res = 0; unordered_set<ll> st;
rep (i, y, m) st.insert(b[i]);
rep (i, x, n) if (st.count(a[i])) ++res; ans = res;
for (int i = x, j = y, k = y; i <= n && j <= m; ++i) {
if (st.count(a[i])) --res;
while (j <= m && b[j] <= a[i]) ++j;
for (; j <= m && ((i < n && b[j] < a[i + 1]) || i == n); ++j) {
while (b[j] - b[k] > i - x) ++k;
umax(ans, res + min(j - k + 1, i - x + 1));
}
}
return ans;
}
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n >> m; int x = n + 1, y = m + 1; a[0] = b[0] = -1;
rep (i, 1, n) { cin >> a[i]; if (a[i - 1] * a[i] < 0) x = i; }
rep (i, 1, m) { cin >> b[i]; if (b[i - 1] * b[i] < 0) y = i; }
reverse(a + 1, a + x); reverse(b + 1, b + y);
rep (i, 1, x - 1) a[i] = -a[i];
rep (i, 1, y - 1) b[i] = -b[i];
cout << work(x, y, n, m) + work(1, 1, x - 1, y - 1) << '\n';
}
return 0;
}
D - Dogeforces
好氣, 沒輸出總經理, 最后沒時間改了, 艹, B卡太長時間了, 各種枚舉情況, 直接狀壓枚舉不就好了.... 暴力都不會
貪心, 為了防止有的經理沒有兩個下屬, 盡量多添加經理, 比如 a[i][j] = a[x][y] = c, 直接 i,j 從屬 e, x,y 從屬 e,
而不是 i,j,x,y 從屬於一個經理, 導致最后 i,j,x,y的上上級只有 i,j,x,y 的上級 這一個下屬
從低到高枚舉工資, 並查集添加經理即可, 還是模擬, 最壞情況就是每兩個員工有個經理, 成線段樹的空間棵 N * 4
vector<PII> h[N * 10];
int b[N << 2], f[N << 4], a[N << 4], fa[N << 4];
int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); }
int main() {
IOS; cin >> n; k = n; int mx = 0;
rep(i, 1, n) f[i] = i;
rep(i, 1, n) rep(j, 1, n) {
cin >> m;
if (i == j) b[i] = m;
else if (i < j) h[m].pb(i, j), umax(mx, m);
}
rep(i, 1, mx - 1) {
if (h[i].empty()) continue;
int cur = k;
for (auto& j : h[i]) fa[j.fi] = find(j.fi), fa[j.se] = find(j.se);
for (auto& j : h[i]) f[find(fa[j.fi])] = find(fa[j.se]);
for (auto& j : h[i]) {
int x = find(j.fi);
if (x <= cur) b[++k] = i, f[x] = f[k] = k, x = k;
a[fa[j.fi]] = a[fa[j.se]] = x;
}
} b[++k] = mx;
for (auto& i : h[mx]) a[find(i.fi)] = a[find(i.se)] = k;
cout << k << '\n';
rep(i, 1, k) cout << b[i] << ' '; cout << '\n';
cout << k << '\n';
rep(i, 1, k - 1) cout << i << ' ' << a[i] << '\n';
return 0;
}
E - A-Z Graph
忘了和哪一次了, 差不多, 讓你選奇數和偶數的回文對稱路徑,
這道比那道還簡單, 為偶數有兩個點存在邊且字符相同 yes, 為奇數, 兩個點互相有邊即可
unordered_map<int, char> h[N];
int main() {
IOS; cin >> n >> m; int x = 0, y = 0;
rep (i, 1, m) {
char op; cin >> op;
if (op == '+') {
int u, v; char c; cin >> u >> v >> c;
h[u][v] = c;
auto it = h[v].find(u);
if (it != h[v].end() && it->se == c) ++x;
if (it != h[v].end()) ++y;
} else if (op == '-') {
int u, v; cin >> u >> v;
auto aa = h[u].find(v), it = h[v].find(u);
if (it != h[v].end() && it->se == aa->se) --x;
if (it != h[v].end()) --y;
h[u].erase(aa);
} else {
int k; cin >> k;
if (k & 1) cout << (y ? "YES\n" : "NO\n");
else cout << (x ? "YES\n" : "NO\n");
}
}
return 0;
}