# | Time | Username | Problem | Language | Result | Execution time | Memory |
---|---|---|---|---|---|---|---|
666818 | LFFB | Ball Machine (BOI13_ballmachine) | C++14 | 1092 ms | 16768 KiB |
This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
#define debug(args...) //printf(args)
#define all(x) x.begin(),x.end()
typedef long long llong;
const int MAX_N = 1e5 + 10;
const int MAX_Q = 1e5 + 10;
int n, q;
int root;
int currentPointer = 0;
bool hasBall[MAX_N];
int parent[MAX_N];
std::vector<int> children[MAX_N];
bool marked[MAX_N];
void addChild(int x) {
if (x == parent[x]) return;
if (marked[x]) return;
marked[x] = true;
children[parent[x]].push_back(x);
addChild(parent[x]);
}
void calculateChildren() {
for (int i = 0; i < n; i++) {
addChild(i);
}
}
namespace Conversion {
int currentLabel = 0;
int label[MAX_N];
int unlabel[MAX_N];
int oldParent[MAX_N];
std::vector<int> oldChildren[MAX_N];
void calculateLabel(int node) {
for (int child : children[node]) {
calculateLabel(child);
}
label[node] = currentLabel;
unlabel[currentLabel] = node;
debug("relabling %d -> %d\n", node, currentLabel);
currentLabel++;
}
void calculateLabels() {
calculateLabel(root);
}
void relabel() {
for (int i = 0; i < n; i++) {
oldParent[i] = parent[i];
}
for (int i = 0; i < n; i++) {
parent[label[i]] = label[oldParent[i]];
}
for (int i = 0; i < n; i++) {
for (int child : children[i]) oldChildren[i].push_back(child);
}
for (int i = 0; i < n; i++) {
children[label[i]].clear();
for (int child : oldChildren[i]) children[label[i]].push_back(label[child]);
}
}
}
void fallPointer() {
for (int child : children[currentPointer]) {
if (hasBall[child]) continue;
debug("falling pointer from %d to %d\n", currentPointer, child);
currentPointer = child;
fallPointer();
return;
}
debug("didnt fall pointer from %d\n", currentPointer);
}
int addBall() {
debug("adding ball to %d\n", currentPointer);
if (hasBall[currentPointer]) {
printf("Something went wrong, tried to add ball to occupied spot(%d)\n", currentPointer);
exit(1);
}
int answer = currentPointer;
hasBall[currentPointer] = true;
currentPointer = parent[currentPointer];
fallPointer();
return answer;
}
int addBalls(int x) {
debug("adding %d balls\n", x);
int answer;
for (int i = 0; i < x; i++) answer = addBall();
return answer;
}
int removeBall(int x) {
debug("removing ball %d\n", x);
if (!hasBall[x]) {
printf("Something went wrong, trying to remove ball from empty spot %d\n", x);
exit(1);
}
int count = 0;
while (x != root && hasBall[parent[x]]) {
x = parent[x];
count++;
debug("x = %d\n", x);
}
hasBall[x] = false;
if (x < currentPointer) currentPointer = x;
debug("setting pointer to %d\n", currentPointer);
return count;
}
int main() {
scanf("%d %d", &n, &q);
for (int i = 0; i < n; i++) {
scanf("%d", &parent[i]);
parent[i]--;
if (parent[i] == -1) {
parent[i] = i;
root = i;
}
}
calculateChildren();
Conversion::calculateLabels();
Conversion::relabel();
root = Conversion::label[root];
for (int query = 0; query < q; query++) {
debug("----- query %d -----\n", query);
int type, x;
scanf("%d %d", &type, &x);
if (type == 1) {
int answer = addBalls(x);
printf("%d\n", Conversion::unlabel[answer] + 1);
} else if (type == 2) {
int answer = removeBall(Conversion::label[x - 1]);
printf("%d\n", answer);
}
}
}
Compilation message (stderr)
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |