Submission #1015919

#TimeUsernameProblemLanguageResultExecution timeMemory
1015919caterpillowBall Machine (BOI13_ballmachine)C++17
100 / 100
290 ms22352 KiB
#include <bits/stdc++.h>

using namespace std;

#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")

using ll = long long;
using pl = pair<ll, ll>;
using pi = pair<int, int>;
#define vt vector
#define f first
#define s second
#define pb push_back
#define all(x) x.begin(), x.end() 
#define size(x) ((int) (x).size())
#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define ROF(i, a, b) for (int i = (b) - 1; i >= (a); i--)
#define F0R(i, b) FOR (i, 0, b)
#define endl '\n'
const ll INF = 1e18;
const int inf = 1e9;

template<template<typename> class Container, typename T>
ostream& operator<<(ostream& os, Container<T> o) {
    os << "{"; 
    int g = size(o); 
    for (auto i : o) os << i << ((--g) == 0 ? "" : ", "); 
    os << "}";
    return os;
}

void _print() {
    cerr << "\n";
}

template<typename T, typename ...V>
void _print(T t, V... v) {
    cerr << t; if (sizeof...(v)) cerr << ", "; _print(v...);
}

#ifdef LOCAL
#define dbg(x...) cerr << #x << " = "; _print(x);
#else
#define dbg(x...)
#define cerr if (0) std::cerr
#endif

/*

removing a ball just deletes its most ancestor ancestor
balls have a fixed "preferred path" at any given state

if a node has a ball in it, then so does its entire subtree

given some tree, there is a fixed priority among active nodes

*/

#ifdef LOCAL
const int sz = 1 << 4;
#else
const int sz = 1 << 17;
#endif

struct LazySeg {
    vt<int> seg, lazy;
    void init() {
        seg.resize(2 * sz, 1);
        lazy.resize(2 * sz, -1);
        ROF (i, 1, sz) seg[i] = seg[2 * i] + seg[2 * i + 1]; 
    }
    void pull(int i) {
        seg[i] = seg[2 * i] + seg[2 * i + 1]; 
    }
    void push(int i, int l, int r) {
        if (lazy[i] == -1) return;
        seg[i] = lazy[i] * (r - l + 1);
        if (l != r) F0R (j, 2) lazy[2 * i + j] = lazy[i]; 
        lazy[i] = -1;
    }
    void upd(int lo, int hi, int v, int i = 1, int l = 0, int r = sz - 1) {
        push(i, l, r);
        if (lo > r || hi < l) return;
        if (lo <= l && r <= hi) {
            lazy[i] = v;
            push(i, l, r);
            return;
        }
        int m = (l + r) / 2;
        upd(lo, hi, v, 2 * i, l, m);
        upd(lo, hi, v, 2 * i + 1, m + 1, r);
        pull(i);
    }
    int query(int lo, int hi, int i = 1, int l = 0, int r = sz - 1) {
        push(i, l, r);
        if (lo > r || hi < l) return 0;
        if (lo <= l && r <= hi) return seg[i];
        int m = (l + r) / 2;
        return query(lo, hi, 2 * i, l, m) + query(lo, hi, 2 * i + 1, m + 1, r);
    }
    int walk(int k, int i = 1, int l = 0, int r = sz - 1) {
        if (l == r) return l;
        int m = (l + r) / 2;
        push(2 * i, l, m), push(2 * i + 1, m + 1, r);
        if (seg[2 * i] >= k) return walk(k, 2 * i, l, m);
        else return walk(k - seg[2 * i], 2 * i + 1, m + 1, r);
    }
};

int n, q, t; 
vt<int> adj[100005];
vt<int> depth, pri, rpri, mn;
LazySeg seg;

int jmp[17][100005];
int maxd;

int dp(int u) {
    int res = u;
    for (int v : adj[u]) {
        res = min(res, dp(v));
    }
    return mn[u] = res;
}

void dfs(int u, int p = -1) {
    for (int v : adj[u]) {
        depth[v] = depth[u] + 1;
        dfs(v, u);
    }
    rpri[t] = u;    
    pri[u] = t++;
}

int lift(int u) {
    auto good = [&] (int v) {
        return seg.query(pri[v], pri[v]) == 0;  
    };
    ROF (i, 0, maxd) {
        if (good(jmp[i][u])) u = jmp[i][u];
    }
    return u;
}


main() {
    cin.tie(0)->sync_with_stdio(0);
    
    cin >> n >> q;
    depth = pri = rpri = mn = vt<int>(n);
    int rt = -1;
    F0R (i, n) {
        int p; cin >> p;
        p--;
        if (p >= 0) {
            jmp[0][i] = p;
            adj[p].pb(i);
        } else {
            rt = i;
            jmp[0][rt] = rt;
        }
    }
    while ((1 << maxd) <= n) maxd++;
    FOR (i, 1, maxd) {
        F0R (u, n) {
            jmp[i][u] = jmp[i - 1][jmp[i - 1][u]];
        }
    }

    seg.init();
    dp(rt);
    F0R (i, n) sort(all(adj[i]), [&] (int u, int v) { return mn[u] < mn[v]; });
    dfs(rt, rt);

    F0R (i, q) {
        int t, u; cin >> t >> u;
        if (t == 1) { // insert balls
            int r = seg.walk(u);
            seg.upd(0, r, 0);
            cout << rpri[r] + 1 << endl;
        } else if (t == 2) {
            u--;
            int v = lift(u);
            seg.upd(pri[v], pri[v], 1);
            cout << depth[u] - depth[v] << endl;
        } else assert(0);
    }
}

Compilation message (stderr)

ballmachine.cpp:147:1: warning: ISO C++ forbids declaration of 'main' with no type [-Wreturn-type]
  147 | main() {
      | ^~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...