topcoder srm 703 div1
problem1 link
按照$x$从小到大排序。然后从前向后处理,当前节点依次与前面已经处理的节点连边。
problem2 link
在$x$ 轴上有$n$个点A,$x$轴上方有$n$个点B,A集合中的每个点在B集合中的每个点找到一个匹配点,B集合中每个点只能与A中的一个点匹配,使得$n$条线段任意两条线段不相交。问有多少种方法。
思路:将B集合按照$y$坐标排序。A集合按照$x$排序。每次枚举A中的一个点与B中最高的点连线,这样分成两段,继续进行这样的匹配。
problem3 link
对每个节点进行哈希,找到同样的节点的个数,然后乘起来.
code for problem1
#include <algorithm> #include <vector> class DAGConstruction { public: std::vector<int> construct(const std::vector<int> &x) { size_t n = x.size(); std::vector<long long> f(n, 0); std::vector<int> ans, V; std::vector<std::pair<int, int>> p; for (size_t i = 0; i < n; ++i) { f[i] = 1ll << i; p.push_back(std::make_pair(x[i], i)); } std::sort(p.begin(), p.end()); auto Get = [&](long long x) { int cnt = 0; for (size_t i = 0; i < n; ++i) { if ((x & (1ll << i)) != 0) { ++cnt; } } return cnt; }; for (size_t i = 0; i < n; ++i) { int c = p[i].first; int u = p[i].second; for (size_t j = 0; j < V.size(); ++j) { int t = V[V.size() - 1 - j]; if (((f[u] & f[t]) != f[t]) && Get(f[u] | f[t]) <= c) { f[u] |= f[t]; ans.push_back(u); ans.push_back(t); } } V.push_back(u); if (Get(f[u]) < c) { return {-1}; } } return ans; } };
code for problem2
#include <algorithm> #include <map> #include <vector> class CoastGuard { public: static constexpr int kMod = 1000000007; int count(const std::vector<int> &d, const std::vector<int> &x, const std::vector<int> &y) { n = static_cast<int>(d.size()); this->as = d; std::sort(as.begin(), as.end()); bs.clear(); cache.clear(); cache.resize(n); std::vector<int> s(n); for (int i = 0; i < n; ++i) { bs.emplace_back(std::make_pair(x[i], y[i])); s[i] = i; cache[i].resize(n); } std::sort(bs.begin(), bs.end(), [&](const std::pair<int, int> &a, const std::pair<int, int> &b) { return a.second < b.second; }); return Dfs(0, n - 1, s); } private: int Dfs(int L, int R, const std::vector<int> &s) { if (s.size() <= 1) { return 1; } { auto iter = cache[L][R].find(s); if (iter != cache[L][R].end()) { return iter->second; } } long long ans = 0; for (int i = L; i <= R; ++i) { int x1 = bs[s.back()].first - as[i]; int y1 = bs[s.back()].second; std::vector<int> ls, rs; bool ok = true; for (size_t j = 0; j + 1 < s.size(); ++j) { int x0 = bs[s[j]].first - as[i]; int y0 = bs[s[j]].second; int sgn = x0 * y1 - x1 * y0; if (sgn == 0) { ok = false; break; } if (sgn < 0) { ls.push_back(s[j]); } else { rs.push_back(s[j]); } } if (ok && ls.size() == i - L && rs.size() == R - i) { ans += 1ll * Dfs(L, i - 1, ls) * Dfs(i + 1, R, rs) % kMod; } } return cache[L][R][s] = static_cast<int>(ans % kMod); } std::vector<int> as; std::vector<std::pair<int, int>> bs; int n; std::vector<std::vector<std::map<std::vector<int>, int>>> cache; };
code for problem3
#include <algorithm> #include <vector> class AutomorphicGraph { public: int count(int n, const std::vector<int> &a, const std::vector<int> &b) { std::vector<std::vector<int>> g(n); for (size_t i = 0; i < a.size(); ++i) { g[a[i]].emplace_back(b[i]); g[b[i]].emplace_back(a[i]); } auto Hash = [&](int num, std::vector<long long> *p) { constexpr int kMagicKey = 19891101; auto curr = *p; for (int t = 0; t < num; ++t) { for (int i = 0; i < n; ++i) { std::vector<long long> values(g[i].size()); for (size_t j = 0; j < g[i].size(); ++j) { values[j] = p->at(g[i][j]); } std::sort(values.begin(), values.end()); for (long long v : values) { curr[i] = curr[i] * kMagicKey + v; } } *p = curr; } }; constexpr int kMod = 1000000007; long long result = 1; std::vector<int> visit(n, 0); std::vector<long long> ss(n, 0); for (int i = 0; i < n; ++i) { std::vector<long long> p(n, 0); for (int j = i; j < n; ++j) { for (int k = 0; k < n; ++k) { p[k] = visit[k] + n; } p[j] += 1; Hash(6, &p); ss[j] = p[j]; } Hash(n + 10, &ss); int c = 0; for (int j = i; j < n; ++j) { if (ss[j] == ss[i]) { ++c; } } result = result * c % kMod; visit[i] = i + n + 1; } return static_cast<int>(result); } };
DAGConstruction