Submission #162772

#TimeUsernameProblemLanguageResultExecution timeMemory
162772faremyRegions (IOI09_regions)C++14
0 / 100
8042 ms32240 KiB
#include <iostream> #include <algorithm> #include <vector> const int MAXN = 2e5; const int MAXR = 25e3; const int SQRTN = 450; std::vector<int> tree[MAXN]; int color[MAXN]; int ofColor[MAXR]; int dfsPre[MAXN], dfsPost[MAXN]; int order[MAXR], revOrder[MAXR]; int ofNewColor[MAXR]; int onOfColor[MAXR]; std::vector<int> ancestersOfColor[MAXR]; std::vector<int> intervalStarts[MAXR]; std::vector<int> intervalEnds[MAXR]; int analysetree(int node, int seen) { ofColor[color[node]]++; dfsPre[node] = seen; int subseen = 1; for (int child : tree[node]) subseen += analysetree(child, seen + subseen); dfsPost[node] = seen + subseen; return (subseen + 1); } void recolor(int colors, int nodes) { for (int iColor = 0; iColor < colors; iColor++) order[iColor] = iColor; std::sort(order, order + colors, [](int a, int b) { return (ofColor[a] > ofColor[b]); }); for (int iColor = 0; iColor < colors; iColor++) ofNewColor[iColor] = ofColor[order[iColor]]; for (int iColor = 0; iColor < colors; iColor++) ofColor[iColor] = ofNewColor[iColor]; for (int iColor = 0; iColor < colors; iColor++) revOrder[order[iColor]] = iColor; for (int iNode = 0; iNode < nodes; iNode++) color[iNode] = revOrder[color[iNode]]; } void buildpartialanswers(int node, int colors, int bigColors) { if (color[node] < bigColors) for (int iColor = 0; iColor < colors; iColor++) ancestersOfColor[color[node]][iColor] += onOfColor[iColor]; else for (int iColor = 0; iColor < bigColors; iColor++) ancestersOfColor[color[node]][iColor] += onOfColor[iColor]; intervalStarts[color[node]].emplace_back(dfsPre[node]); intervalEnds[color[node]].emplace_back(dfsPost[node]); onOfColor[color[node]]++; for (int child : tree[node]) buildpartialanswers(child, colors, bigColors); onOfColor[color[node]]--; } long long countbyfusion(int ancCol, int descCol) { int iAnc = 0, maxEnd = -1; int ancesterPairs = 0; for (int iDesc = 0; iDesc < ofColor[descCol]; iDesc++) { for (; iAnc < ofColor[ancCol] && intervalStarts[ancCol][iAnc] < intervalStarts[descCol][iDesc]; iAnc++) maxEnd = std::max(maxEnd, intervalEnds[ancCol][iAnc]); ancesterPairs += (maxEnd > intervalEnds[descCol][iDesc]); } return ancesterPairs; } int main() { int nodes, colors, queries; std::cin >> nodes >> colors >> queries; for (int iNode = 0; iNode < nodes; iNode++) { if (iNode > 0) { int parent; std::cin >> parent; tree[parent - 1].emplace_back(iNode); } std::cin >> color[iNode]; color[iNode]--; } analysetree(0, 0); recolor(colors, nodes); int bigColors = 0; while (bigColors < colors && ofColor[bigColors] > SQRTN) bigColors++; for (int iColor = 0; iColor < colors; iColor++) { if (iColor < bigColors) ancestersOfColor[iColor].resize(colors, 0); else ancestersOfColor[iColor].resize(bigColors, 0); } buildpartialanswers(0, colors, bigColors); for (int iQuery = 0; iQuery < queries; iQuery++) { int ancCol, descCol; std::cin >> ancCol >> descCol; ancCol = revOrder[ancCol - 1]; descCol = revOrder[descCol - 1]; if (descCol < bigColors || ancCol < bigColors) std::cout << ancestersOfColor[descCol][ancCol] << '\n'; else std::cout << countbyfusion(ancCol, descCol) << '\n'; std::cout << std::flush; } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...