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