結果
問題 | No.5016 Worst Mayor |
ユーザー | Jiro_tech15 |
提出日時 | 2023-04-29 14:32:52 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 13,368 bytes |
コンパイル時間 | 3,248 ms |
コンパイル使用メモリ | 175,928 KB |
実行使用メモリ | 26,016 KB |
スコア | 0 |
最終ジャッジ日時 | 2023-04-29 14:33:03 |
合計ジャッジ時間 | 10,371 ms |
ジャッジサーバーID (参考情報) |
judge12 / judge11 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | TLE | - |
testcase_01 | -- | - |
testcase_02 | -- | - |
testcase_03 | -- | - |
testcase_04 | -- | - |
testcase_05 | -- | - |
testcase_06 | -- | - |
testcase_07 | -- | - |
testcase_08 | -- | - |
testcase_09 | -- | - |
testcase_10 | -- | - |
testcase_11 | -- | - |
testcase_12 | -- | - |
testcase_13 | -- | - |
testcase_14 | -- | - |
testcase_15 | -- | - |
testcase_16 | -- | - |
testcase_17 | -- | - |
testcase_18 | -- | - |
testcase_19 | -- | - |
testcase_20 | -- | - |
testcase_21 | -- | - |
testcase_22 | -- | - |
testcase_23 | -- | - |
testcase_24 | -- | - |
testcase_25 | -- | - |
testcase_26 | -- | - |
testcase_27 | -- | - |
testcase_28 | -- | - |
testcase_29 | -- | - |
testcase_30 | -- | - |
testcase_31 | -- | - |
testcase_32 | -- | - |
testcase_33 | -- | - |
testcase_34 | -- | - |
testcase_35 | -- | - |
testcase_36 | -- | - |
testcase_37 | -- | - |
testcase_38 | -- | - |
testcase_39 | -- | - |
testcase_40 | -- | - |
testcase_41 | -- | - |
testcase_42 | -- | - |
testcase_43 | -- | - |
testcase_44 | -- | - |
testcase_45 | -- | - |
testcase_46 | -- | - |
testcase_47 | -- | - |
testcase_48 | -- | - |
testcase_49 | -- | - |
ソースコード
namespace atcoder {} #ifdef LOCAL #define dbg(x) cerr << __LINE__ << " : " << #x << " = " << (x) << endl; #else // #define NDEBUG #define dbg(x) true; #pragma GCC target("avx2") #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") #endif #ifdef GTEST #include <gtest/gtest.h> #endif #include <math.h> #include <algorithm> #include <array> #include <bitset> #include <cassert> #include <chrono> #include <cstdlib> #include <cstring> #include <functional> #include <iomanip> #include <iostream> #include <limits> #include <list> #include <map> #include <numeric> #include <queue> #include <set> #include <sstream> #include <stack> #include <string> #include <tuple> #include <unordered_map> #include <unordered_set> #include <vector> #ifdef PERF #include <gperftools/profiler.h> #endif using namespace std; using namespace atcoder; #define fast_io \ ios_base::sync_with_stdio(false); \ cin.tie(0); \ cout.tie(0); #define ll long long int #define rep(i, n) for (int i = 0; i < (int)(n); i++) #define reps(i, n) for (int i = 1; i <= (int)(n); i++) #define REP(i, n) for (int i = n - 1; i >= 0; i--) #define REPS(i, n) for (int i = n; i > 0; i--) #define MOD (long long int)(1e9 + 7) #define INF (int)(1e9) #define LINF (long long int)(1e18) #define chmax(a, b) a = (((a) < (b)) ? (b) : (a)) #define chmin(a, b) a = (((a) > (b)) ? (b) : (a)) #define all(v) v.begin(), v.end() typedef pair<int, int> Pii; typedef pair<ll, ll> Pll; constexpr double PI = acos(-1); #ifdef NDEBUG #define CHECK(v1, op, v2) #else #define CHECK(v1, op, v2) \ if (!((v1)op(v2))) { \ cerr << "ERROR:" << (v1) << " " << (v2) << endl; \ assert((v1)op(v2)); \ } #endif long double nCr(const int n, const int r) { long double ret = 1; rep(t, r) { ret *= (n - t); ret /= (r - t); } return ret; } template <typename T> string to_string(const vector<T>& vec) { string ret = ""; rep(i, vec.size()) { ret += vec[i].to_string(); if (i + 1 != vec.size()) { ret += ","; } } return ret; } template <typename T> ostream& operator<<(ostream& os, const vector<T>& vec) { os << to_string(vec); return os; } uint32_t xorshift() { static uint32_t x = 12345789; static uint32_t y = 362436069; static uint32_t z = 521288629; static uint32_t w = 88675123; uint32_t t; t = x ^ (x << 11); x = y; y = z; z = w; w ^= t ^ (t >> 8) ^ (w >> 19); return w; } int rand(const uint32_t l, const uint32_t r) { return xorshift() % (r - l) + l; } uint32_t rand_other_than(const uint32_t l, const uint32_t r, const uint32_t other) { const uint32_t num = rand(l, r - 1); return num + (num >= other); } template <typename T> const T& rand_vec(const vector<T>& vec) { assert(vec.size() > 0); return vec[rand(0, vec.size())]; } template <typename T> void shuffle(vector<T>& vec) { rep(l, (int)vec.size() - 1) { const int idx = rand(l, vec.size()); swap(vec[idx], vec[l]); } } class Timer { chrono::system_clock::time_point _start, _end; ll _sum = 0, _count = 0; public: void start() { _start = chrono::system_clock::now(); } void stop() { _end = chrono::system_clock::now(); } void add() { const chrono::system_clock::time_point now = chrono::system_clock::now(); _sum += static_cast<double>( chrono::duration_cast<chrono::nanoseconds>(now - _start).count()); _count++; } ll sum() const { return _sum / 1000; } int count() const { return _count; } string average() const { if (_count == 0) { return "NaN"; } return to_string(_sum / 1000 / _count); } void reset() { _start = chrono::system_clock::now(); _sum = 0; _count = 0; } inline int ms() const { const chrono::system_clock::time_point now = chrono::system_clock::now(); return static_cast<double>( chrono::duration_cast<chrono::microseconds>(now - _start).count() / 1000); } inline int ns() const { const chrono::system_clock::time_point now = chrono::system_clock::now(); return static_cast<double>( chrono::duration_cast<chrono::microseconds>(now - _start).count()); } }; #ifdef LOCAL struct Timers : unordered_map<string, Timer> { friend ostream& operator<<(ostream& os, const Timers& timers) { for (const auto& pa : timers) { os << pa.first << " time: " << pa.second.sum() / 1000 << " count: " << pa.second.count() << endl; } return os; } }; #else struct Timers { struct Dummy { void start() const {} void add() const {} }; Dummy dummy; const Dummy& operator[](const std::string& str) { return dummy; } friend ostream& operator<<(ostream& os, const Timers& timers) { return os; } }; #endif Timers global_timers; /* start */ vector<double> PARAMS = {}; enum Dir { // y-1, y+1, x-1, x+1 kU, kD, kL, kR }; struct Pos { int idx_; Pos() {} explicit Pos(const int _idx) : idx_(_idx) {} Pos(int _x, int _y) : idx_(_y * N + _x) { assert(N > 0); } int X() const { return pos_2_x[*this]; } int Y() const { return pos_2_y[*this]; } int Idx() const { return idx_; } operator int() const { return Idx(); } operator size_t() const { return Idx(); } const vector<Pos>& Adj() const { return adj_poses[*this]; } const vector<Dir>& AdjDirs() const { return adj_dirs[*this]; } int Manhattan(const Pos& other) const { return abs(X() - other.X()) + abs(Y() - other.Y()); } int Euclid2(const Pos& other) const { const int dx = X() - other.X(); const int dy = Y() - other.Y(); return dx * dx + dy * dy; } bool Move(const Dir dir) { if (move_to[dir][*this].IsDummy()) { return false; } else { *this = move_to[dir][*this]; return true; } } bool operator<(const Pos& other) const { return this->Idx() < other.Idx(); } bool operator==(const Pos& other) const { return this->Idx() == other.Idx(); } bool operator!=(const Pos& other) const { return this->Idx() != other.Idx(); } friend ostream& operator<<(ostream& os, const Pos& pos) { os << pos.X() << " " << pos.Y(); return os; } bool IsDummy() const { return this->idx_ < 0; } static Pos Dummy() { Pos p; p.idx_ = -1; return p; } static Pos TryCreate(const int x, const int y, const int z) { if (y < 0 || y >= N || x < 0 || x >= N) { return Pos::Dummy(); } else { return Pos(x, y); } } static void StaticInit(const int n) { N = n; N2 = N * N; N4 = N2 * N2; adj_poses = vector<vector<Pos>>(N2); adj_dirs = vector<vector<Dir>>(N2); move_to = vector<vector<Pos>>(4, vector<Pos>(N2, Pos::Dummy())); pos_2_y.resize(N2); pos_2_x.resize(N2); rep(y, N) { rep(x, N) { const Pos p{x, y}; pos_2_y[p] = y; pos_2_x[p] = x; for (int dy = -1; dy <= 1; ++dy) { for (int dx = -1; dx <= 1; ++dx) { if (abs(dy) + abs(dx) != 1) continue; const int adj_y = y + dy; const int adj_x = x + dx; if (adj_y < 0 || adj_y >= N) continue; if (adj_x < 0 || adj_x >= N) continue; adj_poses[p].emplace_back(adj_x, adj_y); Dir dir; if (dy == -1) { dir = kU; } else if (dy == 1) { dir = kD; } else if (dx == -1) { dir = kL; } else if (dx == 1) { dir = kR; } else { assert(false); } move_to[dir][p] = {adj_x, adj_y}; adj_dirs[p].emplace_back(dir); } } } } } static int N, N2, N4; static vector<vector<Pos>> adj_poses; static vector<vector<Dir>> adj_dirs; static vector<vector<Pos>> move_to; static vector<int> pos_2_x, pos_2_y; }; vector<vector<Pos>> Pos::adj_poses; vector<vector<Dir>> Pos::adj_dirs; vector<vector<Pos>> Pos::move_to; vector<int> Pos::pos_2_x, Pos::pos_2_y; int Pos::N, Pos::N2, Pos::N4; /* start */ int N, T; vector<Pos> Ss, Gs; enum ActionKind { kBuild, kHuman, kMoney }; struct Action { ActionKind kind; Pos p0, p1; }; struct Solution { Solution() {} static void StaticInit() {} friend ostream& operator<<(ostream& os, const Solution& sol) { return os; } }; /* start */ struct Road { Pos p0, p1; }; struct ROI { Pos p0, p1, s, g; ROI(const Pos& _pa, const Pos& _pb) : p0(min(_pa.X(), _pb.X()), min(_pa.Y(), _pb.Y())), p1(max(_pa.X(), _pb.X()), max(_pa.Y(), _pb.Y())), s(_pa), g(_pb) {} }; class Solver { public: Solver(istream& _is) : is(_is) { is >> N >> T; Pos::StaticInit(14); Ss.reserve(N); Gs.reserve(N); rep(i, N) { int a, b, c, d; is >> a >> b >> c >> d; a--; b--; c--; d--; Ss.emplace_back(b, a); Gs.emplace_back(d, c); } } vector<pair<Road, int>> GreedyOrder() const { vector<pair<Road, int>> order; vector<ROI> rois; vector<vector<bool>> exists(30, vector<bool>(30, false)); // ROI初期化 rep(i, N) { rois.emplace_back(Ss[i], Gs[i]); } rep(t, T) { if (order.size() == 13 * 14 * 2) { break; } //各ROIに対してimos vector<vector<int>> imos(30, vector<int>(30, 0)); for (const auto& roi : rois) { imos[roi.p0.Y() * 2][roi.p0.X() * 2] += 1; imos[roi.p0.Y() * 2][roi.p1.X() * 2 + 1] += -1; imos[roi.p1.Y() * 2 + 1][roi.p0.X() * 2] += -1; imos[roi.p1.Y() * 2 + 1][roi.p1.X() * 2 + 1] += 1; } // imos rep(y, 30) { rep(x, 29) { imos[y][x + 1] += imos[y][x]; } } rep(x, 30) { rep(y, 29) { imos[y + 1][x] += imos[y][x]; } } // 一番偉い辺 Road best_road; int best_count = -1; rep(y, 14) { rep(x, 14) { // y+1 if (y + 1 < 14 && !exists[y * 2 + 1][x * 2]) { const int count = imos[y * 2 + 1][x * 2]; // cerr << count << endl; if (count > best_count) { best_count = count; best_road = Road{Pos{x, y}, Pos{x, y + 1}}; } } // x+1 if (x + 1 < 14 && !exists[y * 2][x * 2 + 1]) { const int count = imos[y * 2][x * 2 + 1]; if (count > best_count) { best_count = count; best_road = Road{Pos{x, y}, Pos{x + 1, y}}; } } } } if (best_count <= 0) break; order.emplace_back(best_road, best_count); exists[best_road.p0.Y() + best_road.p1.Y()] [best_road.p0.X() + best_road.p1.X()] = true; // roiの更新 vector<ROI> next_rois; next_rois.reserve(rois.size() * 2); const auto& p0 = best_road.p0; const auto& p1 = best_road.p1; for (const auto& roi : rois) { // s,gをroadのp0,p1のどちらに対応させるか // dist + dist + 1 == 元のdist Pos s = roi.s; Pos g = roi.g; if (s.Manhattan(p0) + g.Manhattan(p1) + 1 == s.Manhattan(g)) { } else if (s.Manhattan(p1) + g.Manhattan(p0) + 1 == s.Manhattan(g)) { swap(s, g); } else { // 通過しない next_rois.emplace_back(roi); continue; } // s,p0とg,p1が誕生 if (s != p0) { next_rois.emplace_back(s, p0); } if (g != p1) { next_rois.emplace_back(g, p1); } } rois = std::move(next_rois); } return order; } Solution Solve(const int time_limit) const { auto order = GreedyOrder(); // 番兵 order.emplace_back(Road{Pos{0, 0}, Pos{0, 1}}, -INF); int next_order_idx = 0; rep(t, T) { ll u, v; is >> u >> v; const ll cost = (ll)((long double)1e7 / sqrt((long double)v) + 0.01); if (cost > u) { // 建設不可能 // 今後建設をするのか? // 立てることによる今後の収益からcost引いた額よりも、50000連打のほうが偉いなら立てない if (((ll)60 * order[next_order_idx].second) * (T - t) - cost <= 50000 * (T - t)) { assert(t > 100); cout << 3 << endl; continue; } else { cout << 2 << endl; continue; } } // 建設可能 const ll cost_diff = cost - (ll)((long double)1e7 / sqrt((long double)(v + 1)) + 0.01); if (60 * order[next_order_idx].second < cost_diff) { //今日の収益より協力者のコスト低減のほうが偉い cout << 2 << endl; } else { const auto road = order[next_order_idx++].first; cout << 1 << " " << road.p0.X() + 1 << " " << road.p0.Y() + 1 << " " << road.p1.X() + 1 << " " << road.p1.Y() + 1 << endl; } } std::quick_exit(0); return Solution(); } istream& is; }; int main(int argc, char* argv[]) { fast_io; if (argc >= 2) { int idx = 0; for (int i = 1; i < argc; ++i) { PARAMS[idx++] = std::stod(argv[i]); } } Timer timer; timer.start(); Solver solver(cin); auto sol = solver.Solve(1850 - timer.ms()); cout << sol << endl; return 0; }