codeforces educational round 25
A 出题人不给样例解释。。。具体程序
#include<bits/stdc++.h> using namespace std; int n; char s[100]; int main() { scanf("%d%s", &n, s + 1); int ans = 0, tot = 0; for(int i = 1; i <= n; ++i) { if(s[i] == '1') ++tot; else { ans = ans * 10 + tot; tot = 0; } } printf("%d\n", ans * 10 + tot); return 0; }
B 枚举每个点填上黑子,然后判断
#include<bits/stdc++.h> using namespace std; const int dx[] = {0, 1, -1, -1}, dy[] = {1, 1, 1, 0}; int n; char Map[20][20]; bool check() { for(int i = 1; i <= 10; ++i) for(int j = 1; j <= 10; ++j) if(Map[i][j] == 'X') { for(int k = 0; k < 4; ++k) { int xx = i, yy = j; bool flag = true; for(int l = 0; l < 4; ++l) { xx += dx[k], yy += dy[k]; if(Map[xx][yy] != 'X') { flag = false; break; } } if(flag) return true; } } return false; } int main() { memset(Map, 'O', sizeof(Map)); for(int i = 1; i <= 10; ++i) scanf("%s", Map[i] + 1); for(int i = 1; i <= 10; ++i) for(int j = 1; j <= 10; ++j) if(Map[i][j] == '.') { char c = Map[i][j]; Map[i][j] = 'X'; if(check()) { puts("YES"); return 0; } Map[i][j] = c; } puts("NO"); return 0; }
C 贪心,不够就乘2,每次和a取大
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1010; int n, ans; ll k; ll a[N]; int main() { scanf("%d%d", &n, &k); for(int i = 1; i <= n; ++i) scanf("%lld", &a[i]); sort(a + 1, a + n + 1); for(int i = 1; i <= n; ++i) { while(k < (a[i] + 1ll) / 2ll) { ++ans; k = 2ll * k; } if(k >= (a[i] + 1ll) / 2ll) k = max(k, a[i]); } printf("%d\n", ans); return 0; }
D 贪心,能互相交换肯定能换成那个目标串,所以看现在缺少目标串哪个元素就加上
#include<bits/stdc++.h> using namespace std; const int N = 1000010; char s[N], t[N]; int cnt[27], cnt1[27]; int main() { scanf("%s%s", s + 1, t + 1); int len1 = strlen(t + 1), len2 = strlen(s + 1); for(int i = 1; i <= len1; ++i) ++cnt[t[i] - 'a']; for(int i = 1; i <= len2; ++i) if(s[i] != '?') ++cnt1[s[i] - 'a']; for(int i = 1; i <= len2; ++i) { bool flag = false; if(s[i] == '?') { int pos = 0; for(int j = 0; j < 26; ++j) if(cnt1[j] < cnt[j]) { ++cnt1[j]; flag = true; pos = j; break; } if(!flag) { for(int j = 0; j < 26; ++j) cnt1[j] -= cnt[j]; for(int j = 0; j < 26; ++j) if(cnt1[j] < cnt[j]) { ++cnt1[j]; pos = j; break; } } printf("%c", (char)(pos + 'a')); } else printf("%c", s[i]); } return 0; }
E 贪心,证明待填
#include<bits/stdc++.h> using namespace std; const int N = 100010; int n, m; priority_queue<int> q; vector<int> G[N]; int c[N], d[N]; int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= m; ++i) { int u, v; scanf("%d%d", &u, &v); G[v].push_back(u); ++d[u]; } for(int i = 1; i <= n; ++i) if(!d[i]) q.push(i); for(int i = n; i; --i) { int x = q.top(); q.pop(); c[x] = i; for(int j = 0; j < G[x].size(); ++j) { int v = G[x][j]; --d[v]; if(!d[v]) q.push(v); } } for(int i = 1; i <= n; ++i) printf("%d ", c[i]); return 0; }
F dp dp[i]=min(dp[j-1]+calc(j, i)),calc可以先预处理lcp,然后暴力枚举串的长度,看是否符合 这个跑不过去,要4s
#include<bits/stdc++.h> using namespace std; const int N = 8010; int n; int dp[N][N], f[N], sum[N]; char s[N]; int getlen(int x) { int ret = 0; while(x) { ++ret; x /= 10; } return ret; } int main() { scanf("%s", s + 1); n = strlen(s + 1); for(int i = n; i; --i) for(int j = n; j >= i; --j) if(s[i] == s[j]) dp[i][j] = dp[i + 1][j + 1] + 1; memset(f, 0x3f3f, sizeof(f)); f[0] = 0; for(int i = 1; i <= 8000; ++i) sum[i] = sum[i / 10] + 1; for(int i = 1; i <= n; ++i) for(int j = i; j; --j) for(int k = i - j + 1; k > 0 && dp[k][i - j + 1] >= j; k -= j) f[i] = min(f[i], f[k - 1] + j + sum[(i - k + 1) / j]); printf("%d\n", f[n]); return 0; }
G dfs 思路很好,把第一个变成黑点的点作为根,然后预处理出每个点到根的最小值,每次查询直接拿自己的最小值和上次答案比较,因为上次的答案这次肯定也能用,更新就是把当前的最小值和ans取min
#include<bits/stdc++.h> using namespace std; const int N = 1000010; int opt, x, n, q, last, ans = 1 << 29; int up[N]; vector<int> G[N]; void dfs(int u, int last) { for(int i = 0; i < G[u].size(); ++i) { int v = G[u][i]; if(v == last) continue; up[v] = min(v, up[u]); dfs(v, u); } } int main() { scanf("%d%d", &n, &q); for(int i = 1; i < n; ++i) { int u, v; scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } scanf("%d%d", &opt, &x); x = (x + last) % n + 1; up[x] = x; dfs(x, 0); q--; while(q--) { scanf("%d%d", &opt, &x); x = (x + last) % n + 1; if(opt == 1) ans = min(ans, up[x]); if(opt == 2) { printf("%d\n", min(ans, up[x])); last = min(ans, up[x]); } } return 0; }