QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#344773 | #7736. Red Black Tree | ucup-team992 | WA | 204ms | 32580kb | C++23 | 3.2kb | 2024-03-05 09:50:07 | 2024-03-05 09:50:07 |
Judging History
answer
//
// Created by codicon on 3/2/2024 at 6:08 PM.
//
// sum over nodes with > 1 child of (# children * dist to closest_leaf in subtree)
// = O(N)!!!
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5+1;
int n;
string s;
int ans[MAXN];
vector<int> adj[MAXN];
int ptr[MAXN];
pair<vector<int>, array<int, 2>> cost[MAXN]; // {cost, {reds, blacks} in chain above}
struct minq {
deque<int> dq;
queue<int> q;
int min() {
if (empty(dq)) {
return 1e9;
}
return dq.front();
}
void push(int x) {
q.push(x);
while (!empty(dq) and dq.back() < x) {
dq.pop_back();
}
dq.push_back(x);
}
void pop() {
if (q.front() == dq.front()) {
dq.pop_front();
}
q.pop();
}
};
vector<int> reel_up(const pair<vector<int>, array<int, 2>>& cost_chain, int d) {
vector<int> nc(d);
auto [c, _] = cost_chain;
auto [r, b] = _;
minq left, right;
int ladd = 0, radd = 0;
for (int i = 0; i < d; i++) {
// Left
ladd++;
// add
if (b <= i and i < b + size(c)) {
left.push(c[i-b] - ladd);
}
// remove
if (b <= i-(r+1) and i-(r+1) < b + size(c)) {
left.pop();
}
// Right
radd--;
// add
if (b <= i+b and i+b < b + size(c)) {
right.push(c[i+b-b]+b - radd);
}
// remove
if (b <= i and i < b + size(c)) {
right.pop();
}
nc[i] = min(left.min() + ladd, right.min() + radd);
}
return nc;
}
void solve(int c) {
if (size(adj[c]) == 0) {
ptr[c] = c;
cost[c] = {{0}, {}};
cost[c].second[s[c] == '1']++;
ans[c] = 0;
}
else if (size(adj[c]) == 1) {
int ne = adj[c][0];
solve(ne);
ptr[c] = ptr[ne];
cost[ptr[c]].second[s[c] == '1']++;
ans[c] = ans[ne];
}
else {
int min_d = 1e9;
for (auto ne: adj[c]) {
solve(ne);
min_d = min(min_d, (int)size(cost[ptr[ne]].first)
+ cost[ptr[ne]].second[0] + cost[ptr[ne]].second[1]);
}
ptr[c] = c;
cost[c].first.assign(min_d, 0);
cost[c].second = {};
cost[c].second[s[c] == '1']++;
// O(N) amortized!!
for (auto ne: adj[c]) {
vector<int> ne_cost = reel_up(cost[ptr[ne]], min_d);
for (int i = 0; i < min_d; i++) {
cost[c].first[i] += ne_cost[i];
}
}
ans[c] = *min_element(cost[c].first.begin(), cost[c].first.end());
}
}
int main() {
cin.tie(0)->sync_with_stdio(0);
int t; cin >> t;
while (t--) {
cin >> n;
cin >> s;
for (int i = 0; i < n; i++) {
adj[i].clear();
}
for (int i = 1; i <= n - 1; i++) {
int p;
cin >> p;
p--;
adj[p].push_back(i);
}
solve(0);
for (int i = 0; i < n; i++) {
cout << ans[i] << " \n"[i==n-1];
}
}
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 3868kb
input:
2 9 101011110 1 1 3 3 3 6 2 2 4 1011 1 1 3
output:
4 1 2 0 0 0 0 0 0 2 0 0 0
result:
ok 2 lines
Test #2:
score: -100
Wrong Answer
time: 204ms
memory: 32580kb
input:
6107 12 000000001000 1 2 3 2 5 4 4 7 3 8 11 19 1100111101111011110 1 2 1 1 4 5 2 4 3 2 2 7 10 2 11 3 15 5 7 0111110 1 1 2 2 1 5 3 000 1 1 7 1000011 1 2 3 3 5 4 7 0001001 1 1 1 3 5 3 8 00111000 1 1 3 2 5 2 7 11 11111110111 1 1 1 4 5 4 5 2 5 1 15 110101101000010 1 2 3 2 1 5 2 5 6 5 8 7 9 14 10 0101000...
output:
1 1 1 1 0 0 0 0 0 0 0 0 9 5 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 1 0 0 0 0 3 1 0 0 0 0 0 0 4 0 0 2 1 0 0 0 0 0 0 4 4 0 0 2 0 0 0 0 0 0 0 0 0 0 2 0 1 0 0 0 0 0 0 0 7 5 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 6 1 0 1 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 6 4 ...
result:
wrong answer 2nd lines differ - expected: '6 2 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0', found: '9 5 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0'