做着做着cf就坐下了
1344A Hilbert’s Hotel 题目里 $i+a_{i\bmod n}$ 给我整懵了,难道不应该是 $(i+a_i)\bmod n$🐎 所以按上述第二式处理结果,并转至$[0,n)$的范围内,查重即可,$O(n\log n),也可O(n)$。
a.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <bits/stdc++.h> using namespace std ;int main () { int q; cin >> q; while (q--) { int n; cin >> n; vector <int > a (n) ; for (int i = 0 ; i < n; ++i) { cin >> a[i]; a[i] += i; if (a[i] < 0 ) a[i] = (a[i] % n) + n; a[i] %= n; } sort(a.begin (), a.end ()); a.resize(unique(a.begin (), a.end ()) - a.begin ()); if (a.size () != n) cout << "NO" << endl ; else cout << "YES" << endl ; } return 0 ; }
1344B Monopole Magnets 有一个网格,可以放任意数目的$N,S$,每次可以选择一对同一行/列的$N,S$,使$N$向$S$移动$1$。 要求使用最少的$N$,满足:
每一行/列至少有一个$S$;
每一个黑色格子都可以被访问到;
每一个白色格子都不能被访问到。
首先可以想到如果合法的情况下,给每个黑格子都放入$S$,不会影响答案;那么就可以想到如果合法,最小的答案就是连通块的个数,$bfs$处理。 现在思考哪些情况不合法:
如果对于某一列/行,在一个白块的两侧有黑色格子,那么这一列/行都不能含有$S$,违背条件$1$;
如果某一行/列只有白色,那么至少有一列/行也是全白的,这样$S$可以放在交点处,才能满足条件$1$。
$O(nm)$
b.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 #include <bits/stdc++.h> using namespace std; typedef pair<int, int> pii; const int N = 1e3 + 5 ; int n, m, cnt; int to[4 ][2 ] = {1 , 0 , -1 , 0 , 0 , 1 , 0 , -1 }; char g[N ][N ]; bool l[N ][N ], r[N ][N ], u[N ][N ], d[N ][N ]; void bfs(int x, int y) { ++cnt; queue<pii> q; q.emplace(x, y); g[x][y] = '.' ; while (!q.empty()) { pii t = q.front(); q.pop(); for (auto i : to) { pii tt = t; tt.first += i[0 ]; tt.second += i[1 ]; if (tt.first < 1 || tt.first > n || tt.second < 1 || tt.second > m) continue; if (g[tt.first][tt.second] != '#' ) continue; g[tt.first][tt.second] = '.' ; q.emplace(tt); } } } bool check() { for (int i = 1 ; i <= n; ++i) { for (int j = 1 ; j <= m; ++j) { l[i][j] = l[i][j - 1 ]; if (g[i][j - 1 ] == '#' ) l[i][j] = true; } } for (int i = 1 ; i <= n; ++i) { for (int j = m; j >= 0 ; --j) { r[i][j] = r[i][j + 1 ]; if (g[i][j + 1 ] == '#' ) r[i][j] = true; } } for (int i = 1 ; i <= n; ++i) { for (int j = 1 ; j <= m; ++j) { u[i][j] = u[i - 1 ][j]; if (g[i - 1 ][j] == '#' ) u[i][j] = true; } } for (int i = n; i >= 0 ; --i) { for (int j = 1 ; j <= m; ++j) { d[i][j] = d[i + 1 ][j]; if (g[i + 1 ][j] == '#' ) d[i][j] = true; } } bool row = false, col = false; for (int i = 1 ; i <= n; ++i) { if (!r[i][0 ]) row = true; } for (int i = 1 ; i <= m; ++i) { if (!d[0 ][i]) col = true; } if (row ^ col) { // cout << "empty difference WRONG" << endl; return true; } for (int i = 1 ; i <= n; ++i) { for (int j = 1 ; j <= m; ++j) { if (g[i][j] == '.' && ((u[i][j] && d[i][j]) || (l[i][j] && r[i][j]))) { // cout << "black wight blacck WRONG" << endl; return true; } } } return false; } int main() { cin >> n >> m; for (int i = 1 ; i <= n; ++i) { cin >> (g[i] + 1 ); } if (check()) { cout << -1 << endl; return 0 ; } for (int i = 1 ; i <= n; ++i) { for (int j = 1 ; j <= m; ++j) { if (g[i][j] == '#' ) bfs(i, j); } } cout << cnt << endl; return 0 ; }
1344C Quantifier Question $a[l] \& a[l+1] \& \dots \& a[r] = x$ 对于 $f(x_1,x_2…x_n)=(x_{i_1} < x_{j_1}) \& (x_{i_2} < x_{j_2}) \& \dots \& (x_{i_m} < x_{j_m})$,每个$x$变量的量词出现顺序是 $Q_1Q_2…Q_n$,要求全称量词 $\forall$ 最多,使得 $Q_1x_1Q_2x_2\dots Q_nx_nf(x_1,x_2\dots x_n)$ 为真。
首先可以想到与有向图有关,如果图中有环,那么必然不成立,大小关系无法成环,通过拓扑排序判定。 然后在纸上画画又可以发现,只有从小向大放的时候,才有可能出现 $\forall$,因此选择贪心,而且对于图中的一条路,最多只能有一个点是 $\forall$ 的; 如果一个点已经被前面的点已经限制为 $\exists$,那么枚举到它时,会将通过自己的路上的其他点全限制为 $\exists$。 $O(n)$
c.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 #include <bits/stdc++.h> using namespace std ;typedef vector<int > vi; int n, m;bool typo (const vector<vi> &g, vi &ind ) { queue<int > q; for (int i = 1 ; i <= n; ++i) { if (!ind[i]) q.emplace(i); } int cnt = 0 ; while (!q.empty()) { int u = q.front(); q.pop(); ++cnt; for (int v : g[u]) { --ind[v]; if (!ind[v]) q.emplace(v); } } return cnt == n; } void bfs (const vector<vi> &g, vi &vis, int s ) { queue<int > q; q.emplace(s); while (!q.empty()) { int u = q.front(); q.pop(); if (vis[u]) continue ; vis[u] = 1 ; for (int v : g[u]) q.emplace(v); } } int main ( ) { cin >> n >> m; vector<vi> g (n + 1 ), rg (n + 1 ) ; vi ind (n + 1 ) ; for (int i = 0 , u, v; i < m; ++i) { cin >> u >> v; g[u].emplace_back(v); rg[v].emplace_back(u); ++ind[v]; } if (!typo(g, ind)) { cout << -1 << endl; return 0 ; } int cnt = 0 ; string ans; vi vis (n + 1 ), rvis (n + 1 ) ; for (int i = 1 ; i <= n; ++i) { if (vis[i] || rvis[i]) ans += "E" ; else { ++cnt; ans += "A" ; } bfs(g, vis, i); bfs(rg, rvis, i); } cout << cnt << endl << ans << endl; return 0 ; }
本文标题: Codeforces Round 639 Div.1&2 题解
文章作者: WGree
发布时间: 2020-05-09
最后更新: 2020-05-13
原始链接: https://blog.wgree.site/2829846434/
版权声明: 禁止转载