Submission
Status:
----------
Subtask/Task Score:
0/100
Score: 0
User: a0ms1n
Problemset: ถังดักนิวทริโน
Language: cpp
Time: 0.002 second
Submitted On: 2025-05-28 07:37:15
// เขียนโดยใช้ AI ครับ ผมจะลองเทสว่าโมเดลจะตรวจเจอไหม
// ขอโทษล่วงหน้าครับ
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <functional>
using namespace std;
struct Tank {
int id;
int A;
int B;
vector<int> children;
int total_nested_count;
bool is_hit;
};
bool contains(const Tank& t1, const Tank& t2) {
return t1.A <= t2.A && t1.B >= t2.B;
}
void calculateNestedCounts(int u, vector<Tank>& tanks, const vector<vector<int>>& adj) {
tanks[u].total_nested_count = 1;
for (int v : adj[u]) {
calculateNestedCounts(v, tanks, adj);
tanks[u].total_nested_count += tanks[v].total_nested_count;
}
}
void getCoveredHitTanks(int u, const vector<Tank>& tanks, const vector<vector<int>>& adj, vector<bool>& covered_hits) {
if (tanks[u].is_hit) {
covered_hits[tanks[u].id] = true;
}
for (int v : adj[u]) {
getCoveredHitTanks(v, tanks, adj, covered_hits);
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int N, M;
cin >> N >> M;
vector<Tank> tanks(N + 1);
vector<pair<int, int>> initial_coords(N);
for (int i = 0; i < N; ++i) {
tanks[i + 1].id = i + 1;
cin >> tanks[i + 1].A >> tanks[i + 1].B;
initial_coords[i] = {tanks[i + 1].A, tanks[i + 1].B};
tanks[i + 1].is_hit = false;
}
vector<int> hit_tank_ids(M);
for (int i = 0; i < M; ++i) {
cin >> hit_tank_ids[i];
tanks[hit_tank_ids[i]].is_hit = true;
}
vector<vector<int>> adj(N + 1);
vector<vector<int>> parent_adj(N + 1);
for (int i = 1; i <= N; ++i) {
for (int j = 1; j <= N; ++j) {
if (i == j) continue;
if (contains(tanks[i], tanks[j])) {
bool direct_containment = true;
for (int k = 1; k <= N; ++k) {
if (k == i || k == j) continue;
if (contains(tanks[i], tanks[k]) && contains(tanks[k], tanks[j])) {
direct_containment = false;
break;
}
}
if (direct_containment) {
adj[i].push_back(j);
parent_adj[j].push_back(i);
}
}
}
}
tanks.assign(N + 1, Tank());
for (int i = 0; i < N; ++i) {
tanks[i + 1].id = i + 1;
tanks[i + 1].A = initial_coords[i].first;
tanks[i + 1].B = initial_coords[i].second;
tanks[i + 1].is_hit = false;
}
for (int id : hit_tank_ids) {
tanks[id].is_hit = true;
}
adj.assign(N + 1, vector<int>());
parent_adj.assign(N + 1, vector<int>());
for (int i = 1; i <= N; ++i) {
for (int j = 1; j <= N; ++j) {
if (i == j) continue;
if (contains(tanks[i], tanks[j])) {
bool direct_containment = true;
for (int k = 1; k <= N; ++k) {
if (k == i || k == j) continue;
if (contains(tanks[i], tanks[k]) && contains(tanks[k], tanks[j])) {
direct_containment = false;
break;
}
}
if (direct_containment) {
adj[i].push_back(j);
parent_adj[j].push_back(i);
}
}
}
}
vector<int> root_tanks;
for (int i = 1; i <= N; ++i) {
if (parent_adj[i].empty()) {
root_tanks.push_back(i);
}
}
vector<int> num_hit_tanks_in_subtree(N + 1, 0);
function<void(int)> calculateHitCounts = [&](int u) {
if (tanks[u].is_hit) {
num_hit_tanks_in_subtree[u] = 1;
}
for (int v : adj[u]) {
calculateHitCounts(v);
num_hit_tanks_in_subtree[u] += num_hit_tanks_in_subtree[v];
}
};
for (int root : root_tanks) {
calculateNestedCounts(root, tanks, adj);
calculateHitCounts(root);
}
map<int, int> hit_tank_id_to_idx;
for (int i = 0; i < M; ++i) {
hit_tank_id_to_idx[hit_tank_ids[i]] = i;
}
vector<long long> covered_masks(N + 1, 0);
for (int i = 1; i <= N; ++i) {
vector<bool> temp_covered_hits(N + 1, false);
getCoveredHitTanks(i, tanks, adj, temp_covered_hits);
for (int hit_id : hit_tank_ids) {
if (temp_covered_hits[hit_id]) {
covered_masks[i] |= (1LL << hit_tank_id_to_idx[hit_id]);
}
}
}
vector<bool> is_covered_hit(N + 1, false);
vector<int> picked_tanks_result;
int current_total_unrelated = 0;
int current_picked_count = 0;
int num_covered_global = 0;
for (int hit_id : hit_tank_ids) {
if (tanks[hit_id].is_hit) {
num_covered_global++;
}
}
while (num_covered_global < M) {
int best_candidate_id = -1;
int max_newly_covered = -1;
int min_unrelated_cost_for_best = -1;
for (int i = 1; i <= N; ++i) {
bool covers_any_uncovered = false;
long long temp_mask = covered_masks[i];
for (int k = 0; k < M; ++k) {
if ((temp_mask & (1LL << k)) && !is_covered_hit[hit_tank_ids[k]]) {
covers_any_uncovered = true;
break;
}
}
if (!covers_any_uncovered) continue;
int current_newly_covered = 0;
for (int k = 0; k < M; ++k) {
if ((temp_mask & (1LL << k)) && !is_covered_hit[hit_tank_ids[k]]) {
current_newly_covered++;
}
}
int current_unrelated_cost = tanks[i].total_nested_count - num_hit_tanks_in_subtree[i];
if (current_unrelated_cost < 0) current_unrelated_cost = 0;
if (current_newly_covered > max_newly_covered) {
max_newly_covered = current_newly_covered;
best_candidate_id = i;
min_unrelated_cost_for_best = current_unrelated_cost;
} else if (current_newly_covered == max_newly_covered) {
if (current_unrelated_cost < min_unrelated_cost_for_best) {
best_candidate_id = i;
min_unrelated_cost_for_best = current_unrelated_cost;
} else if (current_unrelated_cost == min_unrelated_cost_for_best) {
if (best_candidate_id == -1 || tanks[i].id < tanks[best_candidate_id].id) {
best_candidate_id = i;
min_unrelated_cost_for_best = current_unrelated_cost;
}
}
}
}
if (best_candidate_id == -1) {
break;
}
picked_tanks_result.push_back(tanks[best_candidate_id].id);
current_picked_count++;
current_total_unrelated += min_unrelated_cost_for_best;
long long chosen_mask = covered_masks[best_candidate_id];
for (int k = 0; k < M; ++k) {
if ((chosen_mask & (1LL << k)) && !is_covered_hit[hit_tank_ids[k]]) {
is_covered_hit[hit_tank_ids[k]] = true;
num_covered_global++;
}
}
}
sort(picked_tanks_result.begin(), picked_tanks_result.end());
cout << current_picked_count << endl;
for (int i = 0; i < picked_tanks_result.size(); ++i) {
cout << picked_tanks_result[i] << (i == picked_tanks_result.size() - 1 ? "" : " ");
}
cout << endl;
return 0;
}