Submission #47171

#TimeUsernameProblemLanguageResultExecution timeMemory
47171platypusJakarta Skyscrapers (APIO15_skyscraper)C++17
36 / 100
1085 ms134584 KiB
#include <cstdio> #include <cstdlib> #include <cmath> #include <climits> #include <cfloat> #include <cstring> #include <map> #include <utility> #include <set> #include <iostream> #include <memory> #include <string> #include <vector> #include <list> #include <algorithm> #include <functional> #include <sstream> #include <complex> #include <stack> #include <queue> #include <unordered_set> #include <unordered_map> #include <array> #include <cassert> #include <bitset> using namespace std; using LL = long long; namespace std { template <> class hash<std::pair<int, int>> { public: size_t operator()(const std::pair<int, int>& x) const { //return hash<int>()(x.first) ^ hash<int>()(x.second); return (size_t)(x.second ^ x.first + 0x9e3779b9 + (x.second << 6) + (x.second >> 2)); } }; } //Vは比較可能な値にする template <typename V> class Graph { private: //unordered_map<V, vector<pair<V, LL>>>edge; vector<pair<pair<V, V>, LL>>raw; vector<V>vset; public: //from->toへcostの辺を張る void addEdge(V from, V to, LL cost) { //edge[from].push_back(make_pair(to, cost)); raw.push_back(make_pair(make_pair(from, to), cost)); vset.push_back(from); vset.push_back(to); } //v1とv2間にcostの辺を張る void addUndirectedEdge(V v1, V v2, LL cost) { //edge[v1].push_back(make_pair(v2, cost)); //edge[v2].push_back(make_pair(v1, cost)); raw.push_back(make_pair(make_pair(v1, v2), cost)); raw.push_back(make_pair(make_pair(v2, v1), cost)); vset.push_back(v1); vset.push_back(v2); } //最短を求める void dijkstra(V start, map<V, LL>&dist) { sort(vset.begin(), vset.end()); vset.erase(unique(vset.begin(), vset.end()), vset.end()); int vnum = vset.size(); vector<LL>disti(vnum, LLONG_MAX / 9); unordered_map<V, int>inv; for (int i = 0; i < vnum; ++i) { inv[vset[i]] = i; } vector<vector<pair<int, LL>>>edgei(vnum); for (auto& e : raw) { edgei[inv[e.first.first]].push_back(make_pair(inv[e.first.second], e.second)); } //dist[start] = 0; //priority_queue<pair<LL, V>, vector<pair<LL, V>>, greater<pair<LL, V>>>que; disti[inv[start]] = 0; priority_queue<pair<LL, int>, vector<pair<LL, int>>, greater<pair<LL, int>>>que; que.push(make_pair(0LL, inv[start])); while (!que.empty()) { auto q = que.top(); que.pop(); int now = q.second; LL dis = q.first; if (disti[now] < dis) continue; for (auto e : edgei[now]) { int nxt = e.first; LL cost = e.second; if (/*!disti.count(nxt) ||*/ disti[nxt] > disti[now] + cost) { disti[nxt] = disti[now] + cost; que.push(make_pair(disti[nxt], nxt)); } } } for (int i = 0; i < vnum; ++i) { dist[vset[i]] = disti[i]; } } }; int N, M; int mceil(int a, int b) { if (a == 0)return 0; return (a - 1) / b + 1; } int main(void) { cin >> N >> M; using P = pair<int, int>; map<P, vector<int>>mp; int st = -1; int enb = -1, enp = -1, enr = -1; for (int i = 0; i < M; ++i) { int b, p; cin >> b >> p; if (i == 0)st = b; if (i == 1) { enb = b; enp = p; enr = b % p; } int rem = b % p; mp[make_pair(p, rem)].push_back(b); } Graph<P>G; for (auto elm : mp) { int p = elm.first.first; int rem = elm.first.second; auto& v = elm.second; int len = mceil(N - rem, p); vector<LL>dist(len, INT_MAX); for (int x : v)dist[x / p] = 0; /*for (int i = 1; i < len; ++i) { dist[i] = min(dist[i - 1] + 1, dist[i]); } for (int i = len - 1; i > 0; --i) { dist[i - 1] = min(dist[i] + 1, dist[i - 1]); }*/ for (int i = 0; i < len; ++i) { if (dist[i] < INT_MAX)G.addEdge(P(0, i * p + rem), P(p, i * p + rem), dist[i]); G.addEdge(P(p, i * p + rem), P(0, i * p + rem), 0LL); } for (int i = 1; i < len; ++i) { G.addUndirectedEdge(P(p, (i - 1)*p + rem), P(p, i*p + rem), 1LL); } } int len = mceil(N - enr, enp); for (int i = 0; i < len; ++i) { if (abs(i - (enb / enp)) == 0) G.addEdge(P(0, i * enp + enr), P(N, i * enp + enr), abs(i - (enb / enp))); } map<P, LL> dist; G.dijkstra(P(0, st), dist); LL ans = LLONG_MAX; for (int i = 0; i < len; ++i) { if (abs(i - (enb / enp)) == 0 && dist.count(P(N, i * enp + enr))) ans = min(ans, dist[P(N, i * enp + enr)]); } if (ans >= LLONG_MAX / 9) { cout << -1 << endl; } else { cout << ans << endl; } return 0; }

Compilation message (stderr)

skyscraper.cpp: In member function 'std::size_t std::hash<std::pair<int, int> >::operator()(const std::pair<int, int>&) const':
skyscraper.cpp:36:70: warning: suggest parentheses around arithmetic in operand of '^' [-Wparentheses]
    return (size_t)(x.second ^ x.first + 0x9e3779b9 + (x.second << 6) + (x.second >> 2));
                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...