Submission #299643

#TimeUsernameProblemLanguageResultExecution timeMemory
299643user202729Highway Tolls (IOI18_highway)C++17
100 / 100
261 ms11556 KiB
// moreflags=grader.cpp // :( #include "highway.h" #if not LOCAL #define NDEBUG #endif #include<cassert> #include<vector> #include<cstdint> #include<algorithm> void find_pair(int number, std::vector<int> U, std::vector<int> V, int A, int B) { std::vector<int> query(U.size(), 0); auto const d1=ask(query); // a*(distance from S to T) int i=0; for(int step=1<<20; step>>=1;) if(i+step<(int)U.size()){ query.assign(i+step, 1); query.resize(U.size(), 0); auto const d=ask(query); if(d==d1) i+=step; } // now i is the maximum value such that there's a shortest path not passing through the first i edges // therefore there must be a shortest path passing through edge [i] struct Edge{int node, index;}; std::array<std::vector<Edge>, 2> edges; // edge indices in the bfs tree, split by sourceIndex, // each one is ordered by distance from source node // (node in each edge struct is the node farther from the corresponding source node) std::array<int, 2> source{{U[i], V[i]}}; { // construct adjacency list std::vector<std::vector<Edge>> add(number); for(int index=0; index<(int)U.size(); ++index){ auto const a=U[index], b=V[index]; add[a].push_back({b, index}); add[b].push_back({a, index}); } // multisource bfs from edge [i] struct Item{int node, sourceIndex;}; std::vector<Item> queue; queue.reserve(number); std::vector<char> visited(number); for(int i=0; i<2; ++i){ queue.push_back({source[i], i}); visited[source[i]]=true; } for(int start=0; start<(int)queue.size(); ++start){ auto const [node, sourceIndex]=queue[start]; for(auto [other, edgeIndex]: add[node]) if(not visited[other]){ edges[sourceIndex].push_back({other, edgeIndex}); visited[other]=true; queue.push_back({other, sourceIndex}); } } } std::array<int, 2> result; for(int sourceIndex=0; sourceIndex<2; ++sourceIndex){ int j=(int)edges[sourceIndex].size(); for(int step=1<<20; step>>=1;) if(j-step>=0){ query.assign(U.size(), 1); query[i]=0; for(auto [other, index]: edges[not sourceIndex]) query[index]=0; for(int k=0; k<j-step; ++k) query[edges[sourceIndex][k].index]=0; if(ask(query)==d1) j-=step; } // now j is the smallest value such that the sourceIndex half of the shortest path // is included in the first j nodes of edges[sourceIndex] result[sourceIndex]=j==0 ? source[sourceIndex]: edges[sourceIndex][j-1].node; } answer(result[0], result[1]); }
#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...