結果
| 問題 |
No.5016 Worst Mayor
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2023-04-29 16:58:38 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 123 ms / 2,000 ms |
| コード長 | 7,505 bytes |
| コンパイル時間 | 2,202 ms |
| コンパイル使用メモリ | 178,860 KB |
| 実行使用メモリ | 24,372 KB |
| スコア | 5,652,080,088 |
| 平均クエリ数 | 400.00 |
| 最終ジャッジ日時 | 2023-04-29 17:00:46 |
| 合計ジャッジ時間 | 10,489 ms |
|
ジャッジサーバーID (参考情報) |
judge15 / judge16 |
| 純コード判定しない問題か言語 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 50 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define repn(i, m, n) for (int i = m; i < (int)(n); i++)
#define all(v) v.begin(), v.end()
#define debug(x) cerr << #x << ": " << x << endl;
using Graph = vector<vector<int>>; // グラフ型
template <class T>
bool chmin(T &a, T b)
{
if (a > b)
{
a = b;
return true;
}
else
return false;
}
template <class T>
bool chmax(T &a, T b)
{
if (a < b)
{
a = b;
return true;
}
else
return false;
}
// 定数
#define INF32 2147483647 // 2.147483647×10^{9}:32bit整数のinf
#define INF64 9223372036854775807 // 9.223372036854775807×10^{18}:64bit整数のinf
const ll INF = 1LL << 60;
// const int MOD = 1e9 + 7;
const int MOD = 1000000007;
// 大きい順にソートさせる比較関数を直接渡す
// sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
// modint: mod 計算を int を扱うように扱える構造体
template <int MOD>
struct Fp
{
long long val;
constexpr Fp(long long v = 0) noexcept : val(v % MOD)
{
if (val < 0)
val += MOD;
}
constexpr int getmod() { return MOD; }
constexpr Fp operator-() const noexcept
{
return val ? MOD - val : 0;
}
constexpr Fp operator+(const Fp &r) const noexcept { return Fp(*this) += r; }
constexpr Fp operator-(const Fp &r) const noexcept { return Fp(*this) -= r; }
constexpr Fp operator*(const Fp &r) const noexcept { return Fp(*this) *= r; }
constexpr Fp operator/(const Fp &r) const noexcept { return Fp(*this) /= r; }
constexpr Fp &operator+=(const Fp &r) noexcept
{
val += r.val;
if (val >= MOD)
val -= MOD;
return *this;
}
constexpr Fp &operator-=(const Fp &r) noexcept
{
val -= r.val;
if (val < 0)
val += MOD;
return *this;
}
constexpr Fp &operator*=(const Fp &r) noexcept
{
val = val * r.val % MOD;
return *this;
}
constexpr Fp &operator/=(const Fp &r) noexcept
{
long long a = r.val, b = MOD, u = 1, v = 0;
while (b)
{
long long t = a / b;
a -= t * b;
swap(a, b);
u -= t * v;
swap(u, v);
}
val = val * u % MOD;
if (val < 0)
val += MOD;
return *this;
}
constexpr bool operator==(const Fp &r) const noexcept
{
return this->val == r.val;
}
constexpr bool operator!=(const Fp &r) const noexcept
{
return this->val != r.val;
}
friend constexpr ostream &operator<<(ostream &os, const Fp<MOD> &x) noexcept
{
return os << x.val;
}
friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept
{
if (n == 0)
return 1;
auto t = modpow(a, n / 2);
t = t * t;
if (n & 1)
t = t * a;
return t;
}
};
using mint = Fp<MOD>;
struct UnionFind
{
vector<int> par, siz;
UnionFind(int n) : par(n, -1), siz(n, 1) {}
// search root
int root(int x)
{
if (par[x] == -1)
return x;
else
return par[x] = root(par[x]);
}
// same group?
bool issame(int x, int y)
{
return root(x) == root(y);
}
// unite
bool unite(int x, int y)
{
x = root(x);
y = root(y);
if (x == y)
return false;
if (siz[x] < siz[y])
swap(x, y);
par[y] = x;
siz[x] += siz[y];
return true;
}
int size(int x)
{
return siz[root(x)];
}
};
void dfs(const Graph &G, int v, vector<bool> &seen)
{
seen[v] = true;
for (auto next_v : G[v])
{
if (seen[next_v])
continue;
dfs(G, next_v, seen);
}
return;
}
//
int main()
{
int N, T;
cin >> N >> T;
const int MAXX = 15, MAXY = 15;
vector<int> A(N), B(N), C(N), D(N);
rep(i, N) cin >> A[i] >> B[i] >> C[i] >> D[i];
// とりあえず貪欲に解く
// N人の人の経路に一番重複しそうな区間を選んで工事
// 工事できるまで協力者を集め、集まったら即工事する
vector<vector<int>> x_road_weight(MAXY + 1, vector<int>(MAXX + 1, 0)); // (y,x)から東に出る道の重み
vector<vector<int>> y_road_weight(MAXY + 1, vector<int>(MAXX + 1, 0)); // (y,x)から南に出る道の重み
// 一次元配列にしてソートする
// 各インデックスごとに区間ペアを作っておく
vector<int> road_weight(2 * MAXX * MAXY + 10, 0);
vector<pair<int, int>> road_idx(2 * MAXX * MAXY + 10);
vector<pair<int, int>> next_idx(2 * MAXX * MAXY + 10);
const int NS = MAXX * MAXY; // North to South
const int WE = 0; // West to East
for (int i = 0; i < MAXY; i++)
{
for (int j = 0; j < MAXX; j++)
{
road_idx[WE + i * MAXX + j] = {i, j};
road_idx[NS + i * MAXX + j] = {i, j};
next_idx[WE + i * MAXX + j] = {0, 1};
next_idx[NS + i * MAXX + j] = {1, 0};
}
}
// マンハッタン距離で評価
for (int p = 0; p < N; p++)
{
int nwx = min(B[p], D[p]); // north west
int nwy = min(A[p], C[p]); // north west
int sex = max(B[p], D[p]); // south east
int sey = max(A[p], C[p]); // south east
for (int i = nwy; i < sey; i++)
{
for (int j = nwx; j < sex; j++)
{
road_weight[NS + i * MAXY + j] += 1;
road_weight[WE + i * MAXY + j] += 1;
x_road_weight[i][j] += 1;
y_road_weight[i][j] += 1;
}
}
}
vector<pair<int, int>> sorted_road_weight(2 * MAXX * MAXY + 10);
for (int n = 0; n < 2 * MAXX * MAXY; n++)
{
sorted_road_weight[n] = {road_weight[n], n};
}
sort(all(sorted_road_weight));
reverse(all(sorted_road_weight)); // 降順にする
int construct_count = 0;
ll current_money = 0, current_corps = 0;
// cout << 2 << endl; // 最初はとりあえず集める
bool construct_flag = true;
bool income_flag = false;
for (int step = 0; step < T; step++)
{
cin >> current_money >> current_corps;
ll construct_cost = round(10000000.0 / (double)sqrt(current_corps));
if (current_money == -1 && current_corps == -1)
return 0;
// 建設コストと終了までの収入を比較して、コスト>収入の場合は、人集めにシフト
ll max_delay = -1, max_diff = 0;
for (int delay = 0; delay < T - step; delay++)
{
ll delayed_expected_revenue = 60 * sorted_road_weight[construct_count].first * (T - step - delay);
ll delayed_construct_cost = round(10000000.0 / (double)sqrt(current_corps + delay));
if (chmax(max_diff, delayed_expected_revenue - delayed_construct_cost))
max_delay = delay;
}
if (max_diff > 0 && max_delay <= T - step && max_delay >= 0)
income_flag = false;
else
income_flag = true;
if (max_delay == 0)
construct_flag = true;
else
construct_flag = false;
// ll expected_revenue = 60 * sorted_road_weight[construct_count].first * (T - step);
// if (expected_revenue < construct_cost)
// {
// construct_flag = false;
// }
// else
// construct_flag = true;
if (construct_flag && current_money >= construct_cost)
{
// 建設する
int idx = sorted_road_weight[construct_count].second;
construct_count++;
cout << "1 " << road_idx[idx].first << " " << road_idx[idx].second << " " << road_idx[idx].first + next_idx[idx].first << " " << road_idx[idx].second + next_idx[idx].second << endl;
}
else
{
// 足りなければ協力者を集める
if (income_flag)
cout << "3" << endl;
else
cout << "2" << endl;
}
}
return 0;
}