ABC394
感觉这场 ABC 蛮简单的啊,我这么菜都场切了 \(A\sim F\)
A
int main() {string s; cin >> s;for (int i = 0; i < s.size(); i ++)if (s[i] == '2') cout << 2;return 0;
}
B
const int N = 60;
string s[N];
int n;int main() {cin >> n;for (int i = 1; i <= n; i ++) cin >> s[i];sort(s + 1, s + 1 + n, [&](string a, string b) {return a.size() < b.size();});for (int i = 1; i <= n; i ++) cout << s[i];return 0;}
C
注意不要看错题
int main() {string s; cin >> s;for (int i = s.size() - 1; i >= 1; i --)if (s[i] == 'A' && s[i - 1] == 'W') s[i] = 'C', s[i - 1] = 'A';cout << s << endl;return 0;
}
D
就是一个判断括号序列是否合法的题,使用栈进行匹配即可。
stack<char> stk;
string s;int main() {cin >> s;map<char, char> h;h[']'] = '[', h['>'] = '<', h[')'] = '(';for (int i = 0; i < s.size(); i ++) {if (s[i] == '(' || s[i] == '<' || s[i] == '[') stk.push(s[i]);else {if (stk.empty() || stk.top() != h[s[i]]) {puts("No");return 0;} else stk.pop();}}if (!stk.empty()) puts("No");else puts("Yes");return 0;
}
E
注意到 \(N \leq 100\),考虑暴力广搜。
由于我们需要找回文串,所以考虑确定一个回文中心然后暴力向两边拓展相同的字符。
然后你要注意都是单向边,所以你往外拓展的时候要注意边的方向,并且注意不要重复算,不然时间就爆了。
时间复杂度是 \(O(n^4)\) 的,但实际上跑不到这么高,而且 \(AT\) 时间开 2s 不卡常。
const int N = 110;
int n, d[N][N];
char g[N][N];void bfs(int x, int y) {queue<PII> q;q.push({x, y});if (x == y) d[x][y] = 0;else d[x][y] = 1;while (q.size()) {auto t = q.front(); q.pop();int a = t.first, b = t.second;for (int i = 1; i <= n; i ++)if (g[i][a] != '-') for (int j = 1; j <= n; j ++)if (g[b][j] != '-' && g[i][a] == g[b][j]) {if (d[a][b] + 2 < d[i][j]) {d[i][j] = d[a][b] + 2;q.push({i, j});} } }
}int main() {n = read();for (int i = 1; i <= n; i ++) for (int j = 1; j <= n; j ++)cin >> g[i][j];memset(d, 0x3f, sizeof d);for (int i = 1; i <= n; i ++) for (int j = 1; j <= n; j ++)if (i == j || g[i][j] != '-')bfs(i, j);for (int i = 1; i <= n; i ++, puts(""))for (int j = 1; j <= n; j ++)printf("%d ", d[i][j] == INF ? -1 : d[i][j]);return 0;
}
F
考虑树形 \(DP\)。
先不考虑至少有一个顶点的度数为 \(4\) 这个要求,剩余的条件显然是很好数位 \(DP\) 的。
设 \(ans\) 为全局答案,\(f[u]\) 表示就是祖先所构成的树的一个以 \(u\) 为树根的子树的最大顶点数。那么转移分为两种情况,一种是 \(u\) 的度数为 \(1\),那由于 \(u\) 还有一个父亲连着它,所以 \(u\) 的最大顶点数就是 \(1\);另一种当 \(u\) 的度数为 \(4\) 时,就找 \(u\) 的儿子中 \(f\) 值前三大的 \(f[u_1] + f[u_2] + f[u_3] + 1\)。
然后还要更新全局答案。\(ans\) 就应该用以 \(u\) 为根的子树的最大顶点数更新,度数为 \(4\) 时找出前四大的 \(f[u_1] + f[u_2] + f[u_3] + f[u_4] + 1\) ,\(ans\) 的度数为 \(1\) 时,那就找出最大的 \(f[u_1] + 1\)。
注意这里 \(ans\) 计算的是以 \(u\) 为整棵树根,而不是 \(u\) 为子树根。
最后我要忘记还有一个顶点度数为 \(4\) 的要求,所以最后找出的答案至少要有 \(5\) 个及以上的结点。
const int N = 200010;
int n, a[N], b[N];
int f[N], ans;
int h[N], ne[N << 1], e[N << 1], idx;void add(int a, int b) {e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
} void dp(int u, int fa) {vector<int> sons;f[u] = 1;for (int i = h[u]; ~i; i = ne[i]) {int j = e[i];if (j == fa) continue;dp(j, u);sons.push_back(f[j]);}sort(sons.begin(), sons.end(), [&](int a, int b) {return a > b;});if (sons.size()) ans = max(ans, sons[0] + 1);if (sons.size() >= 3) f[u] = max(f[u], sons[0] + sons[1] + sons[2] + 1);if (sons.size() >= 4) ans = max(ans, sons[0] + sons[1] + sons[2] + sons[3] + 1);
}int main() {n = read();memset(h, -1, sizeof h);for (int i = 1; i < n; i ++) {int a = read(), b = read();add(a, b); add(b, a);}dp(1, -1);printf("%d\n", ans <= 4 ? -1 : ans);return 0;
}
G
待补