Submission #102335

#TimeUsernameProblemLanguageResultExecution timeMemory
102335TomGautotBall Machine (BOI13_ballmachine)C++14
60.08 / 100
1084 ms23280 KiB
#include <bits/stdc++.h> #define INF 999999999 using namespace std; vector<vector<int> > treeAdj; vector<int> smallestInSubtree, freePlacesInSubtree, depth, reverseTree; vector<int> fillOrderId, fillIdToNode; vector<bool> available; priority_queue<int, vector<int>, greater<int> > availableSpots; int n, q; int root; int lastRolledDepth; void computeData(int node, int d){ int chld = treeAdj[node].size(); depth[node] = d; //printf("Getting data for node %d (depth %d)\n", node, d); if(chld == 0){ //printf("IT S A LEAF!\n"); smallestInSubtree[node] = node; freePlacesInSubtree[node] = 1; return; } int sml = node; int fps = 1; int v; vector<pair<int, int> > newSortedAdj; for(int i = 0; i < chld; i++){ v = treeAdj[node][i]; //printf("%d -th child of %d is %d\n", i+1, node, v); computeData(v, d+1); newSortedAdj.push_back({smallestInSubtree[v], v}); sml = min(sml, smallestInSubtree[v]); fps+= freePlacesInSubtree[v]; } sort(newSortedAdj.begin(), newSortedAdj.end()); for(int i = 0; i < chld; i++){ treeAdj[node][i] = newSortedAdj[i].second; } smallestInSubtree[node] = sml; freePlacesInSubtree[node] = fps; //printf("Got data for node %d (depth %d)\n", node, d); return; } int computeFillOrderId(int node, int id){ int sz = treeAdj[node].size(); int v; for(int i = 0; i < sz; i++){ v = treeAdj[node][i]; id = computeFillOrderId(v, id); } fillOrderId[node] = id; fillIdToNode[id] = node; //printf("Node %d has fill order id %d\n", node, id); return id+1; } void fillAllSubtree(int node){ if(freePlacesInSubtree[node] == 0) return; freePlacesInSubtree[node] = 0; int sz = treeAdj[node].size(); for(int i = 0; i < sz; i++){ fillAllSubtree(treeAdj[node][i]); } } int addBalls(int node, int toPlace){ // returns new val after filling subtree of node if(toPlace == 0 || freePlacesInSubtree[node] <= 0) return toPlace; int freePlaces = freePlacesInSubtree[node]; if(freePlaces < toPlace){ fillAllSubtree(node); return toPlace-freePlaces; } else if(freePlaces == toPlace){ // This node is the one to be output fillAllSubtree(node); cout << node+1 << endl; return 0; } int sz = treeAdj[node].size(); //freePlacesInSubtree[node] = 0; int v, placed; for(int i = 0; i < sz && toPlace > 0; i++){ // The children are sorted by minimum id found in subtree v = treeAdj[node][i]; placed = toPlace-addBalls(v, toPlace); freePlacesInSubtree[node]-=placed; toPlace = toPlace-placed; //freePlacesInSubtree[node]+=freePlacesInSubtree[v]; } //cout << "There are now " << freePlacesInSubtree[node] << " in the subtree of " << node << endl; return toPlace; } void removeBall(int val){ int index = val; int last = index; bool addMode = false; while(true){ if(addMode){ freePlacesInSubtree[index]++; if(index == root) return; } else if(freePlacesInSubtree[index] != 0){ lastRolledDepth = depth[last]; freePlacesInSubtree[last]++; addMode = true; continue; } else if(index == root){ lastRolledDepth = depth[root]; freePlacesInSubtree[root]++; return; } last = index; index = reverseTree[index]; } } void printTreeState(){ printf("myIds: "); for(int i = 0; i < n; i++){ printf("%d ", i); } printf("\nDepth: "); for(int i = 0; i < n; i++){ printf("%d ", depth[i]); } printf("\nfpist: "); for(int i = 0; i < n; i++){ printf("%d ", freePlacesInSubtree[i]); } printf("\n"); } void addBallsWithPQ(int val){ int spot; for(int i = 0; i < val; i++){ spot = availableSpots.top(); availableSpots.pop(); available[fillIdToNode[spot]] = false; } cout << fillIdToNode[spot]+1 << endl; } void removeBallWithPQ(int val){ int index = val; int last = index; while(true){ if(available[index]){ lastRolledDepth = depth[last]; if(last != index) availableSpots.push(fillOrderId[last]); available[last] = true; return; } else if(index == root){ lastRolledDepth = depth[root]; if(last != index) availableSpots.push(fillOrderId[root]); available[root] = true; return; } last = index; index = reverseTree[index]; } } int main() { ios::sync_with_stdio(false); cin.tie(); int p; cin >> n >> q; depth.resize(n); reverseTree.resize(n); treeAdj.resize(n); smallestInSubtree.resize(n); freePlacesInSubtree.resize(n); fillIdToNode.resize(n); fillOrderId.resize(n); available.assign(n, true); for(int i = 0; i < n; i++){ cin >> p; if(p == 0) root = i; else{ treeAdj[p-1].push_back(i); reverseTree[i] = p-1; } } //cout << "Going to compute data" << endl; //return 0; computeData(root, 0); computeFillOrderId(root, 0); for(int i = 0; i < n; i++){ availableSpots.push(i); } /* printf("Priority queue content: "); for(int i = 0; i < n; i++){ printf("%d ", availableSpots.top()); availableSpots.pop(); } printf("\n"); for(int i = 0; i < n; i++){ availableSpots.push(i); } */ //return 0; //cout << "Data was computedd successfully" << endl; int action, val; for(int i = 0; i < q; i++){ cin >> action >> val; if(action == 1){ addBallsWithPQ(val); } else{ val--; removeBallWithPQ(val); //cout << "Last rolled depth is " << *lastRolledDepth << endl; cout << depth[val] - lastRolledDepth << endl; } //printTreeState(); } return 0; }

Compilation message (stderr)

ballmachine.cpp: In function 'void addBallsWithPQ(int)':
ballmachine.cpp:159:9: warning: 'spot' may be used uninitialized in this function [-Wmaybe-uninitialized]
     int spot;
         ^~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...