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
"; 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
";
else if (g && y[0] == y[1]) cout << "YES
";
else cout << "NO
";
}
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
" : "NO
");
}
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) << '
';
}
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 << '
';
rep(i, 1, k) cout << b[i] << ' '; cout << '
';
cout << k << '
';
rep(i, 1, k - 1) cout << i << ' ' << a[i] << '
';
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
" : "NO
");
else cout << (x ? "YES
" : "NO
");
}
}
return 0;
}