Submission #290095

#TimeUsernameProblemLanguageResultExecution timeMemory
290095model_codeSpring cleaning (CEOI20_cleaning)C++17
100 / 100
416 ms29948 KiB
#include <iostream> #include <vector> #include <algorithm> #include <map> using namespace std; // // Solution to task Spring-cleaning by Zsolt Németh @birka0 // // Use dfs to compute: node depths, subtree leaf count, // even subtree leaf count on the path to root for all nodes, // the cost of cleaning the tree without adding any leafs. // Preread the whole input and for each node store the question_id-s for which new leaves were attached to it. // Run a second dfs and dynamically maintain (in a bottom-up DP manner) the unpaired extra leaves in each subtree: // the question_id-s are unique for each, and their parent nodes must be stored. // For each internal node, merge these collections of question id-s for all its children // (insert the smaller into the bigger to maintain low complexity). // Whenever we encounter the same question_id twice, we can pair and remove them (as we are in their LCA node). // Store the cleaning cost changes in a vector for each question separately. // int N,Q,D, root=1, dep[100001], leafcnt[100001], even_to_root[100001]; int x,y; int base_ans, mod_ans[100001]; vector<int> e[100001], q_adds[100001]; map<int,int> collect[100001]; int calc_change(int deep_node, int ancestor_node) { return dep[deep_node]-dep[ancestor_node] - 2*(even_to_root[deep_node]-even_to_root[ancestor_node]); } void dfs(int node, int par, int depth = 0) { dep[node] = depth; if (e[node].size()==1) { leafcnt[node] = 1; return; } for (int ch : e[node]) { if (ch == par) continue; dfs(ch, node, depth+1); leafcnt[node] += leafcnt[ch]; } if (leafcnt[node] % 2 == 0) ++base_ans; } int dfs2(int node, int par) { even_to_root[node] = even_to_root[par] + (leafcnt[node]%2 == 0); if (e[node].size() == 1) { for (int k=0; k < q_adds[node].size(); ++k) { int cnt = 1; while (k+1 < q_adds[node].size() && q_adds[node][k]==q_adds[node][k+1]) ++k, ++cnt; if (cnt%2 == 0) collect[node][q_adds[node][k]] = node; } return node; } int coll_id = 0; for (int ch : e[node]) { if (ch == par) continue; int ret_coll = dfs2(ch, node); if (coll_id == 0) coll_id = ret_coll; else { if (collect[coll_id].size() < collect[ret_coll].size()) swap(coll_id, ret_coll); for (auto& qq : collect[ret_coll]) { if (collect[coll_id].count(qq.first)) { int foundnode = collect[coll_id][qq.first]; collect[coll_id].erase(qq.first); mod_ans[qq.first] += calc_change(qq.second, node) + calc_change(foundnode, node); } else collect[coll_id].insert(qq); } } } for (int k=0; k < q_adds[node].size(); ++k) { int cnt = 1; while (k+1 < q_adds[node].size() && q_adds[node][k]==q_adds[node][k+1]) ++k, ++cnt; if (cnt%2 == 1) { if (collect[coll_id].count(q_adds[node][k])) { const auto& qq = collect[coll_id].find(q_adds[node][k]); mod_ans[qq->first] += calc_change(qq->second, node); collect[coll_id].erase(qq); } else collect[coll_id][q_adds[node][k]] = node; } } return coll_id; } int main() { ios::sync_with_stdio(false); cin >> N >> Q; for (int i=1; i<N; ++i) { cin >> x >> y; e[x].push_back(y), e[y].push_back(x); } while (e[root].size() == 1) ++root; base_ans = N-1; dfs(root, 0); for (int q=1; q<=Q; ++q) { cin >> D; mod_ans[q] = D; for (int i=0; i<D; ++i) { cin >> x; q_adds[x].push_back(q); } } int root_coll = dfs2(root, 0); for (int q=1; q<=Q; ++q) { const auto& qq = collect[root_coll].find(q); if (leafcnt[root]%2 == 0 && qq==collect[root_coll].end()) cout << base_ans+mod_ans[q]-1 << endl; else if (leafcnt[root]%2 == 1 && qq!=collect[root_coll].end()) cout << base_ans+mod_ans[q]+calc_change(qq->second,root) << endl; else cout << -1 << endl; } return 0; }

Compilation message (stderr)

cleaning.cpp: In function 'int dfs2(int, int)':
cleaning.cpp:49:25: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   49 |         for (int k=0; k < q_adds[node].size(); ++k) {
      |                       ~~^~~~~~~~~~~~~~~~~~~~~
cleaning.cpp:51:24: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   51 |             while (k+1 < q_adds[node].size() && q_adds[node][k]==q_adds[node][k+1]) ++k, ++cnt;
      |                    ~~~~^~~~~~~~~~~~~~~~~~~~~
cleaning.cpp:73:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   73 |     for (int k=0; k < q_adds[node].size(); ++k) {
      |                   ~~^~~~~~~~~~~~~~~~~~~~~
cleaning.cpp:75:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   75 |         while (k+1 < q_adds[node].size() && q_adds[node][k]==q_adds[node][k+1]) ++k, ++cnt;
      |                ~~~~^~~~~~~~~~~~~~~~~~~~~
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...