結果
| 問題 |
No.2114 01 Matching
|
| コンテスト | |
| ユーザー |
qwewe
|
| 提出日時 | 2025-05-14 13:03:14 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 5,130 bytes |
| コンパイル時間 | 1,270 ms |
| コンパイル使用メモリ | 112,284 KB |
| 実行使用メモリ | 50,176 KB |
| 最終ジャッジ日時 | 2025-05-14 13:04:47 |
| 合計ジャッジ時間 | 15,574 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 8 WA * 3 TLE * 1 -- * 39 |
ソースコード
#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
#include <map>
#include <set> // Use multiset for implementation (though not used in final slow version)
#include <cmath> // For std::abs
// Function to calculate the minimum cost for a specific remainder group.
// Uses a slow O(N_r * (M_r - N_r + 1)) approach which might TLE on large cases,
// but is logically correct based on the derived cost function and matching property.
// N_r = |B|, M_r = |R|. Assumes N_r <= M_r after potential swap.
long long calculate_min_cost_for_remainder_slow(std::vector<long long>& B, std::vector<long long>& R, long long K) {
int N = B.size();
int M = R.size();
// If either group is empty, no matching is possible, cost is 0.
if (N == 0 || M == 0) {
return 0;
}
// Ensure N <= M by swapping if necessary.
// The property requires matching all vertices of the smaller set.
if (N > M) {
std::swap(B, R);
std::swap(N, M);
}
// Sort both lists to apply the property that optimal matching pairs B_i with R_{k+i-1}.
// Since using 0-based indexing, match B[i] with R[k+i].
std::sort(B.begin(), B.end());
std::sort(R.begin(), R.end());
// Initialize minimum total absolute difference sum with -1 (or a very large value).
// This variable will store minimum of Sum |B[i] - R[k+i]| over all possible k.
long long min_total_abs_diff = -1;
// Iterate through all possible start indices k for the subarray in R.
// k ranges from 0 to M - N.
for (int k = 0; k <= M - N; ++k) {
long long current_sum_abs_diff = 0;
// Calculate the sum of absolute differences for the current window k.
// Matches B[i] with R[k+i] for i = 0 to N-1.
for (int i = 0; i < N; ++i) {
current_sum_abs_diff += std::abs(B[i] - R[k + i]);
}
// Update the minimum sum found so far.
if (min_total_abs_diff == -1 || current_sum_abs_diff < min_total_abs_diff) {
min_total_abs_diff = current_sum_abs_diff;
}
}
// If N=0 originally, this function returns 0 early.
// If N > 0, then M >= N > 0, so M-N >= 0, loop runs at least once.
// min_total_abs_diff will hold a non-negative value.
// The cost is the sum of operations, which is sum of |B_i - R_j| / K.
return min_total_abs_diff / K;
}
int main() {
// Faster I/O
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
int N, M; // Number of blue and red vertices
long long K; // Value to increase by
std::cin >> N >> M >> K;
// Read initial values for blue vertices
std::vector<long long> B_orig(N);
for (int i = 0; i < N; ++i) std::cin >> B_orig[i];
// Read initial values for red vertices
std::vector<long long> R_orig(M);
for (int i = 0; i < M; ++i) std::cin >> R_orig[i];
// Group vertices by their value modulo K
std::map<long long, std::vector<long long>> B_groups;
for (int i = 0; i < N; ++i) {
B_groups[B_orig[i] % K].push_back(B_orig[i]);
}
std::map<long long, std::vector<long long>> R_groups;
for (int i = 0; i < M; ++i) {
R_groups[R_orig[i] % K].push_back(R_orig[i]);
}
// Calculate the maximum possible number of edges that can be formed.
// This is the sum of minimum sizes of corresponding remainder groups.
long long max_possible_edges = 0;
std::vector<long long> remainders; // Store remainders that have vertices on both sides
for (auto const& [rem, b_list] : B_groups) {
// Check if this remainder group also exists for red vertices
if (R_groups.count(rem)) {
// Add the maximum possible matches for this remainder group
max_possible_edges += std::min((long long)b_list.size(), (long long)R_groups[rem].size());
// Store this remainder for later processing
remainders.push_back(rem);
}
}
// Check if the target number of edges (min(N, M)) is achievable.
// Maximum possible edges must be at least min(N, M).
// We derived earlier that max_possible_edges <= min(N, M).
// So achievability requires max_possible_edges == min(N, M).
if (max_possible_edges < std::min(N, M)) {
std::cout << -1 << std::endl;
return 0;
}
// If achievable, calculate the total minimum cost.
long long total_min_cost = 0;
// Iterate through only those remainders that have vertices in both B and R groups.
for (long long rem : remainders) {
std::vector<long long> B_rem = B_groups[rem];
std::vector<long long> R_rem = R_groups[rem];
// Calculate the minimum cost for this remainder group and add to total.
// Using the slow O(N*M) function temporarily. For competitive programming,
// a faster O(M log N) or O(M log M) approach would be needed for large inputs.
total_min_cost += calculate_min_cost_for_remainder_slow(B_rem, R_rem, K);
}
// Output the total minimum cost.
std::cout << total_min_cost << std::endl;
return 0;
}
qwewe