There are n castles and m obstacles on a chessboard. Each castle or obstacle occupies exactly one cell and all occupied cells are distinct. Two castles can attack each other, if they’re on the same row or the same column, and there are no obstacles or other castles between them. Find a way to place the minimum number of additional obstacles onto the chessboard, so that no two castles can attack each other.
unordered_map<int, vector<pair<int, int>>> X, Y; int n = read(); for (int i = 0; i < n; ++i) { int x = read(), y = read(); X[x].emplace_back(y, 1); Y[y].emplace_back(x, 1); } int m = read(); for (int i = 0; i < m; ++i) { int x = read(), y = read(); X[x].emplace_back(y, 0); Y[y].emplace_back(x, 0); }
n = boy.size(), m = girl.size(); vector<vector<int>> E(n); for (int u = 0; u < n; ++u) { auto& [x, y1, y2] = boy[u]; for (int v = 0; v < m; ++v) { auto& [y, x1, x2] = girl[v]; if (x1 < x && x < x2 && y1 < y && y < y2) { E[u].push_back(v); } } }
if (ugly) { printf("-1\n"); return; }
vector<int> npy(m, -1); for (int u = 0; u < n; ++u) { vector<int> vis(m, 0); auto dfs = [&](thisauto&& self, int u) -> bool { for (auto& v : E[u]) { if (vis[v]) continue; vis[v] = 1; if (npy[v] == -1 || self(npy[v])) { npy[v] = u; returntrue; } } returnfalse; }; dfs(u); }
vector<pair<int, int>> res; vector<int> happy(n, false); for (int v = 0; v < m; ++v) { if (npy[v] != -1) { happy[npy[v]] = true; res.emplace_back(boy[npy[v]][0], girl[v][0]); } else { auto& [y, x1, x2] = girl[v]; res.emplace_back(x1 + x2 >> 1, y); } } for (int u = 0; u < n; ++u) { if (!happy[u]) { auto& [x, y1, y2] = boy[u]; res.emplace_back(x, y1 + y2 >> 1); } }
int m; cin >> m; unordered_map<int, vector<int>> vec; vector<vector<int>> g(200000); vector<int> n(m); int tot = 0; for (int i = 0; i < m; i++) { cin >> n[i]; for (int j = 0; j < n[i]; j++) { int x; cin >> x; if (j & 1) { g[tot].push_back(tot - 1); g[tot - 1].push_back(tot); } vec[x].push_back(tot); tot++; } }
bool bipartite = true; for (auto [k, v] : vec) { if (v.size() % 2) bipartite = false; for (int i = 1; i < v.size(); i += 2) { g[v[i]].push_back(v[i - 1]); g[v[i - 1]].push_back(v[i]); } }
vector<int> c(tot, -1); for (int s = 0; s < tot; ++s) { if (c[s] != -1) continue; c[s] = 0; queue<int> Q; Q.push(s); while (!Q.empty()) { int u = Q.front(); Q.pop(); for (auto& v : g[u]) { if (c[v] == -1) { c[v] = 1 ^ c[u]; Q.push(v); } elseif (c[v] == c[u]) { bipartite = false; } } } }
if (!bipartite) { cout << "NO\n"; } else { cout << "YES\n"; int tot = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n[i]; j++) { cout << (c[tot++] == 1 ? "L" : "R"); } cout << "\n"; } }
constexprint N = 3e6 + 8; bool isntPrime[N]; vector<int> prime; voidbeforeT(){ for (int i = 2; i < N; ++i) { if (!isntPrime[i]) prime.push_back(i); for (auto& p : prime) { if (p * i >= N) break; isntPrime[p * i] = 1; if (i % p == 0) break; } } isntPrime[1] = 1; }
voideachT(){ int num = read();
int m = 1; while (num - 1 > ((m & 1) ? (m * (m + 1) / 2) : (m * m / 2 + 1))) ++m;
vector<vector<pair<int, int>>> E(m + 1); int id = 0; for (int i = 1; i <= m; ++i) { for (int j = i; j <= m; ++j) { if (m % 2 == 0 && i % 2 == 0 && i + 1 == j) continue; E[i].emplace_back(j, ++id); E[j].emplace_back(i, id); } }
vector<int> vis(id + 1); vector<int> path; auto dfs = [&](thisauto&& self, int u) -> void { while (!E[u].empty()) { auto [v, id] = E[u].back(); E[u].pop_back();
if (vis[id]) continue; vis[id] = 1;
self(v); } path.push_back(u); }; dfs(1);
for (int i = 0; i < num; ++i) { printf("%d ", prime[path[i]]); } }
int n = read(), m = read(), q = read(); DSU dsu(n + m); while (q--) { int x = read(), y = read(); dsu.uno(x, y + n); // WA } int res = 0; for (int i = 1; i <= n + m; ++i) { res += dsu.find(i) == i; } printf("%d\n", res - 1);
int n; string s; cin >> n >> s; vector<int> p(n); for (int i = 0; i < n; i++) { cin >> p[i]; p[i]--; }
ll res = 1; vector<int> vis(n); for (int i = 0; i < n; i++) { if (vis[i]) continue; int u = i; string cyc; do { cyc += s[u]; vis[u] = true; u = p[u]; } while (u != i); auto ncyc = cyc; int t = 0; do { t++; ncyc = ncyc.substr(1) + ncyc[0]; } while (ncyc != cyc); res = lcm(res, t); }
int n; cin >> n; vector<int> p(n); for (int i = 0; i < n; i++) { cin >> p[i]; p[i]--; }
vector<vector<int>> cycs; vector<int> vis(n); for (int i = 0; i < n; i++) { if (vis[i]) continue; int u = i; vector<int> cyc; do { cyc.push_back(u); vis[u] = true; u = p[u]; } while (u != i); cycs.push_back(cyc); }
int res = 0, flag = 0; for (auto& cyc : cycs) { sort(cyc.begin(), cyc.end()); for (int j = 1; j < cyc.size(); j++) { flag |= cyc[j - 1] == cyc[j] - 1; } res += cyc.size() - 1; } cout << (res + 1 - 2 * flag) << "\n";
int n; cin >> n; vector<int> p(n); for (int i = 0; i < n; i++) { cin >> p[i]; p[i]--; }
vector<vector<vector<int>>> cycs(n + 1); vector<int> vis(n); for (int i = 0; i < n; i++) { if (vis[i]) continue; int u = i; vector<int> cyc; do { cyc.push_back(u); vis[u] = true; u = p[u]; } while (u != i); cycs[cyc.size()].push_back(cyc); }
vector<int> res(n); bool ok = true; for (int siz = 1; siz <= n; siz++) { if (siz & 1) { for (auto& cyc : cycs[siz]) { for (int i = 0; i < siz; i++) { res[cyc[i]] = cyc[(i + (siz + 1) / 2) % siz]; } } } elseif (cycs[siz].size() % 2 == 1) { ok = false; break; } elsefor (int k = 1; k < cycs[siz].size(); k += 2) { vector<int>& L = cycs[siz][k - 1], &R = cycs[siz][k]; for (int i = 0; i < siz; i++) { res[L[i]] = R[i]; res[R[i]] = L[(i + 1) % siz]; } } }
if (!ok) { cout << "-1\n"; } elsefor (int i = 0; i < n; i++) { cout << ++res[i] << " "; }
int n; cin >> n; vector<int> pos(n), p(n); for (int i = 0; i < n; i++) { int x; cin >> x; x--; pos[x] = i; } for (int i = 0; i < n; i++) { int x; cin >> x; x--; p[i] = pos[x]; }
vector<vector<int>> cycs; vector<int> vis(n); for (int i = 0; i < n; i++) { if (vis[i]) continue; int u = i; vector<int> cyc; do { cyc.push_back(u); vis[u] = true; u = p[u]; } while (u != i); cycs.push_back(cyc); }
int min = 1, max = n; vector<int> ans(n, -1); for (auto& cyc : cycs) { int siz = cyc.size(); for (int i = 0; i < siz - siz % 2; ++i) { ans[cyc[i]] = i & 1 ? min++ : max--; } } for (int i = 0; i < n; i++) { if (ans[i] == -1) ans[i] = min++; }
ll res = 0; for (int i = 0; i < n; i++) { res += abs(ans[i] - ans[p[i]]); } cout << res << "\n";
例 6 给定n 个二元组(ai,bi),可以按任意次序重新排序,问能否使得排序后数组{a} 的逆序对数和{b} 的逆序对数相同,给出方案。(2024 ICPC 台湾 C. Cards)
int n; cin >> n; vector<pair<int, int>> a(n); vector<int> pos(n), p(n); for (int i = 0; i < n; i++) { int x; cin >> x; x--; pos[x] = i; a[i].first = x; } for (int i = 0; i < n; i++) { int x; cin >> x; x--; p[i] = pos[x]; a[i].second = x; }
vector<vector<pair<int, int>>> cycs; vector<int> vis(n); for (int i = 0; i < n; i++) { if (vis[i]) continue; int u = i; vector<pair<int, int>> cyc; do { cyc.push_back(a[u]); vis[u] = 1; u = p[u]; } while (u != i); cycs.push_back(cyc); }
int tot = 0, cnt = 0; vector<pair<int, int>> res(n); for (auto& cyc : cycs) { constint m = cyc.size(); if (m % 2 == 0) cnt++;
auto tmp = cyc; sort(tmp.begin(), tmp.end()); auto mid = tmp[(m - (cnt % 2)) / 2];
for (int i = 0; i < m; i++) { if (cyc[i] == mid) { for (int j = 0; j < m; j++) { res[tot++] = cyc[(i + j) % m]; } } } }
if (cnt % 2 == 1) { cout << "No\n"; } else { cout << "Yes\n"; for (int i = 0; i < n; i++) { cout << ++res[i].first << " \n"[i == n - 1]; } for (int i = 0; i < n; i++) { cout << ++res[i].second << " \n"[i == n - 1]; } }
int n; cin >> n; vector<vector<int>> E(n + 1); vector<int> p(n + 1); for (int u = 1; u <= n; u++) { int x; cin >> x; int v = u + x; if (v > n || v < 1) v = 0; E[v].push_back(u); p[u] = v; }
vector<int> vis(n + 1), siz(n + 1, 1); auto dfs = [&](thisauto&& self, int u) -> void { for (auto v : E[u]) { if (vis[v]) continue; vis[v] = 1; self(v); siz[u] += siz[v]; } }; vis[0] = 1; dfs(0);
int cnt = count(vis.begin(), vis.end(), 0); ll ans = 0; if (vis[1]) { int u = 1; while (u) { ans += siz[u] + cnt; u = p[u]; } ans = 1ll * n * (2 * n + 1) - ans; } else { int u = 1; while (u && vis[u] != 2) { vis[u] = 2; ans += (2 * n + 1) - cnt; u = p[u]; } } cout << ans << "\n";
#include<cstdio> #include<algorithm> #include<vector> #include<stack> #include<queue> using ll = longlong; constexprint N = 2e6 + 8; constexprint MOD = 1e9 + 7;
inline ll read(){ ll Y = getchar(), S = 0, C = 1; while (Y > 57 || Y < 48) { if (Y == 45) C = -1; Y = getchar(); } while (Y <= 57 && Y >= 48) { S = (S << 3) + (S << 1) + Y - 48; Y = getchar(); } return S * C; }
/// ----------------结构体---------------- structnode { int l = 1e9, r; // 吞噬范围 node& operator+=(constexpr node& other) { l = min(l, other.l); r = max(r, other.r); return *this; } } w[N]; int n, rt[N];
voideachTarjan(int u){ dfn[u] = low[u] = ++unix; // 记录DFS序 S.push(u); // DP更新low[u] for (auto v : E[u]) { if (!dfn[v]) eachTarjan(v), low[u] = min(low[u], low[v]); elseif (!fa[v]) low[u] = min(low[u], dfn[v]); } // u是SCC的根 if (low[u] == dfn[u]) { int top; do { top = S.top(); S.pop(); // 出栈 fa[top] = u; // 记录u的子节点的根为u } while (top != u); // 不断弹出直到根u弹出为止 } }
voidtarjan(int n){ // Tarjan for (int u = 1; u <= n; ++u) { if (!dfn[u]) eachTarjan(u); } // 重构图 将子树的性质嫁接到SCC的根上 for (int u = 1; u <= n; ++u) { for (auto v : E[u]) { if (fa[u] != fa[v]) Etmp[fa[u]].push_back(fa[v]); } // 存储新的边 wtmp[fa[u]] += w[u]; // 存储新的边权 } for (int u = 1; u <= n; ++u) { w[u] = wtmp[u]; E[u] = Etmp[u]; sort(E[u].begin(), E[u].end()); E[u].erase(unique(E[u].begin(), E[u].end()), E[u].end()); } }
int deg[N]; voidtopo(int n){ for (int u = 1; u <= n; ++u) { for (auto v : E[u]) deg[v] += 1; } queue<int> Q; for (int u = 1; u <= n; ++u) { if (!deg[u] && u == fa[u]) Q.push(u); } while (!Q.empty()) { int u = Q.front(); Q.pop(); for (auto to : E[u]) { w[to] += w[u]; deg[to] -= 1; if (!deg[to]) { Q.push(to); } } } }
/// ----------------线段树---------------- #define ls p<<1 #define rs p<<1|1 #define mid ((cl+cr)>>1) #define len (cr-cl+1) #define lson ls,cl,mid #define rson rs,mid+1,cr
// 建树 树上的边先连上 voidbuild(int p = 1, int cl = L, int cr = R){ if (cl == cr) return w[p] = { cl,cl }, rt[cl] = p, void(); E[ls].push_back(p), build(lson); E[rs].push_back(p), build(rson); }
// [l,r]向x连边 voidaddedge(int l, int r, int x, int p = 1, int cl = L, int cr = R){ if (l <= cl && cr <= r) return E[p].push_back(x); if (l <= mid) addedge(l, r, x, lson); if (mid < r) addedge(l, r, x, rson); }
for (int i = 1; i <= n; ++i) { xi[i] = read(), ri[i] = read(); }
build(); for (int i = 1; i <= n; ++i) { int l = lower_bound(xi + 1, xi + n + 1, xi[i] - ri[i]) - xi, // 二分找第一个大于等于 xi[i]-ri[i] 的 l 即是下界 r = upper_bound(xi + 1, xi + n + 1, xi[i] + ri[i]) - xi - 1; // 二分找第一个大于 xi[i]+ri[i] 的 r 即是上界上面的那一个 再 -1 即是上界 addedge(l, r, rt[i]); // Slime i will eat [l,r] // rt[] 数组表示 i 在新图上点的编号是 rt[i] }
tarjan(n << 2), topo(n << 2); // 缩个点再跑一圈
ll res = 0; for (int i = 1; i <= n; ++i) { res += 1ll * i * (w[fa[rt[i]]].r - w[fa[rt[i]]].l + 1); res %= MOD; } printf("%lld", res);