이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <bits/stdc++.h>
using namespace std;
/***
Given a rooted tree, you have to support 2 types of operations:
* paint the root of a full black subtree in black
* check where the path from a black node to the root becomes white
I can do the erases using binary lifting:
* if the 2^k ancestor of node u is black, than all the nodes between them are black
* if not, you can go down the tree
Add operation:
* I will always want to add in the same exact order
* So I will have a vector of 1 and 0, and I want to find the LAST 0
***/
const int LG = 17;
const int MAXN = 1000 * 100;
vector<int> g[MAXN + 1], order[MAXN + 1];
int dad[MAXN + 1], minValue[MAXN + 1], who[MAXN + 1], tin[MAXN + 1];
int ancestor[LG + 1][MAXN + 1];
bool black[MAXN + 1];
priority_queue<int> fr;
void dfs(int u) {
vector<pair<int, int>> children;
for (const int &v : g[u]) {
dfs(v);
minValue[u] = min(minValue[u], minValue[v]);
children.emplace_back(minValue[v], v);
}
sort(children.begin(), children.end());
reverse(children.begin(), children.end());
for (const auto &p : children) {
order[u].push_back(p.second);
}
}
void dfsOrder(int u) {
static int t = 0;
tin[u] = t++;
who[t - 1] = u;
for (const int &v : order[u]) {
dfsOrder(v);
}
}
int add() {
int u = who[fr.top()];
fr.pop();
black[u] = true;
return u;
}
int erase(int u) {
int ans = 0;
for (int l = LG; l >= 0; l--) {
if (black[ancestor[l][u]]) {
u = ancestor[l][u];
ans += (1 << l);
}
}
fr.push(tin[u]);
black[u] = false;
return ans;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
int n, q; cin >> n >> q;
int root = -1;
for (int i = 1; i <= n; i++) {
cin >> dad[i];
if (dad[i] != 0) {
g[dad[i]].push_back(i);
} else {
root = i;
}
}
for (int i = 1; i <= n; i++) {
minValue[i] = i;
fr.push(i - 1);
}
dfs(root);
dfsOrder(root);
for (int u = 1; u <= n; u++) {
ancestor[0][u] = dad[u];
}
for (int k = 1; k <= LG; k++) {
for (int u = 1; u <= n; u++) {
ancestor[k][u] = ancestor[k - 1][ancestor[k - 1][u]];
}
}
for (int i = 0; i < q; i++) {
int op, k; cin >> op >> k;
if (op == 1) {
int u = -1;
for (int j = 0; j < k; j++) {
u = add();
}
cout << u << "\n";
} else {
cout << erase(k) << "\n";
}
}
return 0;
}
# | 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... |