結果
問題 | No.2953 Maximum Right Triangle |
ユーザー | nono00 |
提出日時 | 2024-11-08 22:30:57 |
言語 | C++23 (gcc 12.3.0 + boost 1.83.0) |
結果 |
RE
|
実行時間 | - |
コード長 | 11,412 bytes |
コンパイル時間 | 4,183 ms |
コンパイル使用メモリ | 266,808 KB |
実行使用メモリ | 6,824 KB |
最終ジャッジ日時 | 2024-11-08 22:31:19 |
合計ジャッジ時間 | 4,691 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,248 KB |
testcase_02 | AC | 2 ms
5,248 KB |
testcase_03 | RE | - |
testcase_04 | AC | 2 ms
5,248 KB |
testcase_05 | RE | - |
testcase_06 | RE | - |
ソースコード
#include <algorithm> #include <limits> #include <queue> #include <utility> #include <vector> #include <ranges> #include <utility> #include <vector> namespace nono { template <class T> class CSRArray { using iterator = std::vector<T>::iterator; using const_iterator = std::vector<T>::const_iterator; using subrange = std::ranges::subrange<iterator, iterator>; using const_subrange = std::ranges::subrange<const_iterator, const_iterator>; public: CSRArray() = default; CSRArray(int row_size, const std::vector<std::pair<int, T>>& data) : row_size_(row_size), indptr_(row_size_ + 1), data_(data.size()) { for (auto key: data | std::views::keys) { indptr_[key + 1]++; } for (int i = 0; i < row_size_; i++) { indptr_[i + 1] += indptr_[i]; } auto index = indptr_; for (const auto& [key, value]: data) { data_[index[key]++] = value; } } CSRArray(int row_size, const std::vector<int>& row, const std::vector<T>& data) : row_size_(row_size), indptr_(row_size_ + 1), data_(data.size()) { for (auto key: row) { indptr_[key + 1]++; } for (int i = 0; i < row_size_; i++) { indptr_[i + 1] += indptr_[i]; } auto index = indptr_; for (int i = 0; i < (int)data.size(); i++) { data_[index[row[i]]++] = data[i]; } } subrange operator[](int i) { return std::ranges::subrange(data_.begin() + indptr_[i], data_.begin() + indptr_[i + 1]); } const_subrange operator[](int i) const { return std::ranges::subrange(data_.begin() + indptr_[i], data_.begin() + indptr_[i + 1]); } int all_size() const { return data_.size(); } int size() const { return row_size_; } private: int row_size_; std::vector<int> indptr_; std::vector<T> data_; }; } // namespace nono #include <iterator> #include <ranges> #include <vector> namespace nono { template <class T> struct EdgeBase { int from; int to; T weight; EdgeBase() {} EdgeBase(int from, int to, T weight = 1): from(from), to(to), weight(weight) {} }; using Edge = EdgeBase<int>; template <class T> using WeightedEdge = EdgeBase<T>; template <class T> class Graph { struct Edge_ { int to; T weight; int id; }; using iterator = std::vector<Edge_>::iterator; using const_iterator = std::vector<Edge_>::const_iterator; using subrange = std::ranges::subrange<iterator, iterator>; using const_subrange = std::ranges::subrange<const_iterator, const_iterator>; public: template <class U> friend Graph<U> to_undirected_graph(int n, const std::vector<EdgeBase<U>>& edges); template <class U> friend Graph<U> to_directed_graph(int n, const std::vector<EdgeBase<U>>& edges); subrange operator[](int i) { return std::ranges::subrange(edges_.begin() + indptr_[i], edges_.begin() + indptr_[i + 1]); } const_subrange operator[](int i) const { return std::ranges::subrange(edges_.begin() + indptr_[i], edges_.begin() + indptr_[i + 1]); } int size() const { return n_; } int edge_size() const { return m_; } bool is_directed() const { return directed_; } bool is_undirected() const { return !is_directed(); } private: Graph(int n, const std::vector<EdgeBase<T>>& edges, bool directed) : n_(n), m_(edges.size()), indptr_(n_ + 1), edges_(directed ? edges.size() : 2 * edges.size()), directed_(directed) { for (const auto& e: edges) { indptr_[e.from + 1]++; if (!directed_) indptr_[e.to + 1]++; } for (int i = 0; i < n_; i++) { indptr_[i + 1] += indptr_[i]; } auto index = indptr_; for (int i = 0; i < std::ssize(edges); i++) { const auto& e = edges[i]; edges_[index[e.from]++] = Edge_(e.to, e.weight, i); if (!directed_) edges_[index[e.to]++] = Edge_(e.from, e.weight, i); } } int n_; int m_; std::vector<int> indptr_; std::vector<Edge_> edges_; bool directed_; }; template <class T> Graph<T> to_undirected_graph(int n, const std::vector<EdgeBase<T>>& edges) { return Graph<T>(n, edges, false); } template <class T> Graph<T> to_directed_graph(int n, const std::vector<EdgeBase<T>>& edges) { return Graph<T>(n, edges, true); } } // namespace nono #include <vector> namespace nono { template <class T> bool is_bipartite(const Graph<T>& graph) { int n = graph.size(); std::vector<short> color(n, -1); auto dfs = [&](auto&& self, int u) -> bool { for (auto e: graph[u]) { if (color[e.to] == -1) { color[e.to] = color[u] ^ 1; if (!self(self, e.to)) return false; } else if (color[e.to] == color[u]) { return false; } } return true; }; for (int i = 0; i < n; i++) { if (color[i] == -1) { color[i] = 0; if (!dfs(dfs, i)) return false; } } return true; } } // namespace nono namespace nono { std::vector<int> bipartite_matching(int left, int right, std::vector<std::pair<int, int>> edges) { int m = edges.size(); for (auto& [u, v]: edges) { v += left; } const CSRArray graph(left, edges); const int inf = std::numeric_limits<int>::max(); std::vector<int> adj(left + right, -1); std::vector<int> dist(left + right, inf); std::queue<int> que; while (true) { std::fill(dist.begin(), dist.end(), inf); for (int i = 0; i < left; i++) { if (adj[i] == -1) { dist[i] = 0; que.push(i); } } while (!que.empty()) { int u = que.front(); que.pop(); for (auto v: graph[u]) { if (dist[v] == inf && adj[u] != v) { dist[v] = dist[u] + 1; if (adj[v] != -1) { dist[adj[v]] = dist[v] + 1; que.push(adj[v]); } } } } bool reached = false; for (int i = left; i < left + right; i++) { reached |= dist[i] != inf && adj[i] == -1; } if (!reached) break; auto dfs = [&](auto&& self, int u) -> bool { for (auto v: graph[u]) { if (dist[u] + 1 == dist[v]) { dist[v] = inf; if (adj[v] == -1 || self(self, adj[v])) { adj[u] = v; adj[v] = u; return true; } } } return false; }; for (int i = 0; i < left; i++) { if (adj[i] == -1) { dfs(dfs, i); } } } std::vector<int> result; for (int i = 0; i < m; i++) { auto [u, v] = edges[i]; if (adj[u] == v) { result.push_back(i); adj[u] = -1; } } return result; } template <class T> std::vector<int> bipartite_matching(const Graph<T>& graph) { int n = graph.size(); int m = graph.edge_size(); std::vector<int> mapping(n, -1); std::vector<bool> is_lefts(n); int left = 0, right = 0; auto dfs = [&](auto&& self, int u, bool is_left = true) -> void { is_lefts[u] = is_left; if (is_left) { mapping[u] = left++; } else { mapping[u] = right++; } for (auto e: graph[u]) { if (mapping[e.to] == -1) { self(self, e.to, is_left ^ true); } } }; for (int i = 0; i < n; i++) { if (mapping[i] == -1) { dfs(dfs, i); } } std::vector<std::pair<int, int>> edges(m); for (int u = 0; u < n; u++) { if (!is_lefts[u]) continue; for (auto e: graph[u]) { edges[e.id] = {mapping[u], mapping[e.to]}; } } return bipartite_matching(left, right, edges); } } // namespace nono #include <bits/stdc++.h> using namespace std; using ll = long long; using ld = long double; using ull = unsigned long long; template <class T> using max_heap = priority_queue<T>; template <class T> using min_heap = priority_queue<T, vector<T>, greater<T>>; #define rep(i, l, r) for (ll i = (l); i < (r); i++) #define rrep(i, r, l) for (ll i = (r); i-- > (l);) #define all(x) begin(x), end(x) template <class T> bool chmin(T& lhs, T rhs) { return lhs > rhs ? (lhs = rhs, true) : false; } template <class T> bool chmax(T& lhs, T rhs) { return lhs < rhs ? (lhs = rhs, true) : false; } struct IOIO { IOIO() { cin.tie(0)->sync_with_stdio(0); } } ioio; template <class S, class T> ostream& operator<<(ostream& os, const pair<S, T>& p) { os << '(' << p.first << ", " << p.second << ')'; return os; } template <class T> ostream& operator<<(ostream& os, const vector<T>& vs) { os << '{'; rep(i, 0, (int)vs.size()) os << vs[i] << (i + 1 == (int)vs.size() ? "" : ", "); os << '}'; return os; } template <class T> ostream& operator<<(ostream& os, const set<T>& vs) { os << '{'; for (auto it = vs.begin(); it != vs.end(); it++) { if (it != vs.begin()) { os << ", "; } os << *it; } os << '}'; return os; } template <class T, class U> ostream& operator<<(ostream& os, const map<T, U>& vs) { os << '{'; for (auto it = vs.begin(); it != vs.end(); it++) { if (it != vs.begin()) { os << ", "; } os << *it; } os << '}'; return os; } #ifdef DEBUG void dump_func() { cerr << endl; } template <class Head, class... Tail> void dump_func(Head&& head, Tail&&... tail) { cerr << head; if (sizeof...(Tail) > 0) { cerr << ", "; } dump_func(std::move(tail)...); } #define dump(...) cerr << "[" + string(#__VA_ARGS__) + "] ", dump_func(__VA_ARGS__) #else #define dump(...) static_cast<int>(0) #endif void solve() { ll d, x, y; cin >> d >> x >> y; ll ans = 0; auto F = [&](ll a) { return -((x * (a - x)) / y) + y; }; auto area = [&](ll x1, ll y1, ll x2, ll y2) { return abs((x1 * y2) - (x2 * y1)); }; auto in = [&](ll v) { return 0 <= v && v <= d; }; { ll g = y / gcd(y, x); ll ok = 0; ll ng = (d + g) / g; while (ng - ok > 1) { ll key = (ok + ng) / 2; if (in(g * key + x) && in(F(g * key + x))) ok = key; else ng = key; } chmax(ans, area(x, y, g * ok + x, F(g * ok + x))); } { ll g = y / gcd(y, x); ll ok = 0; ll ng = -((x + g) / g); while (ok - ng > 1) { ll key = (ok + ng) / 2; if (in(g * key + x) && in(F(g * key + x))) ok = key; else ng = key; } chmax(ans, area(x, y, g * ok + x, F(g * ok + x))); } cout << ans << '\n'; } int main() { int t; cin >> t; while (t--) solve(); }